Configure the Client Directory

Let’s now configure the client component. The client directory contains:

  • The index.html file that contains the HTML code for the frontend application
  • The main.css file that contains the CSS code
  • The main.js file that contains the JavaScript code
  • The client-package.json configuration file

We will be coding index.html, main.js and main.css. We will also create a new file login.html in this directory and add code in it.

Note: Please go through the code in this section to make sure you fully understand it. We will discuss the code at the end of this section.

Copy the code below and paste it in the respective files located in the client/ directory of your project using an IDE and save the files.

    
index.html
copy
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>WorkDriveSync</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.19.1/css/mdb.min.css" rel="stylesheet"> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"> </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"> </script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"> </script> <script src="main.js"></script> <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="https://static.zohocdn.com/catalyst/sdk/js/2.0.0/catalystWebSDK.js"></script> <script src="/__catalyst/sdk/init.js"></script> <style> #fileupload { width: 450px; } </style> </head> <body onload="getfiles()"> <center> <br> <h1>Catalyst File Vault</h1> </center> <br> <div style="width: 200px;float: left; margin-left: 50px;"><label for="logoutbtn" class="btn btn-danger btn-block btn-outlined">Logout</label> <button id="logoutbtn" onclick="logout()" style="display: none;"></button> </div> <div style="width: 200px;float: right; margin-right: 50px;"><label for="fileupload" class="btn btn-success btn-block btn-outlined">Upload File</label> <input type="file" id="fileupload" onchange="uploadfile()" name="myfile" style="display: none;"> </div><br><br><br><br> <div class="container"> <ul class="nav nav-tabs nav-justified mb-3" id="myTab" role="tablist"> <li class="nav-item"> <a class="nav-link active " id="check-tab" data-toggle="tab" href="#check" role="tab" aria-controls="check" aria-selected="true">Filestore -> Workdrive Sync</a> </li> </ul><br> <div class="tab-content" id="myTabContent"> <div class="tab-pane fade show active" id="check" role="tabpanel" aria-labelledby="check-tab"> <p id="filestore"></p> <div id="loader" style="display: none;"> <div class="spinner-border" role="status"> <span class="sr-only">Loading...</span> </div> </div> </div> </div> </div> <!-- Modal --> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="vertical-alignment-helper"> <div class="modal-dialog vertical-align-center"> <div class="modal-content"> <center> <h4 class="modal-title" id="myModalLabel"></h4> <div class="modal-body" id="message"></div> <div class="modal-footer"> <button type="button" style="background-color: #007bff;color: white;" class="btn btn-default" data-dismiss="modal">Close</button> </div> </center> </div> </div> </div> </div> <div class="modal fade right" id="ModalDanger" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog modal-notify modal-danger modal-side modal-top-right" role="document"> <!--Content--> <div class="modal-content"> <!--Header--> <div class="modal-header"> <p class="heading">File Deletion</p> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true" class="white-text">×</span> </button> </div> <!--Body--> <div class="modal-body"> <div class="row"> <div class="col-9"> <p>Are you sure you want to delete the file?</p> </div> </div> </div> <!--Footer--> <div class="modal-footer justify-content-center"> <a type="button" class="btn btn-danger" id="delete-btn" onclick="deleteFile()">Delete</a> <a type="button" class="btn btn-outline-danger waves-effect" data-dismiss="modal">Cancel</a> </div> </div> <!--/.Content--> </div> </div> </body> </html>
View more
    
main.css
copy
#dataTable { font-family: Arial, Helvetica, sans-serif; border-collapse: collapse; width: 100%; } #dataTable td, #dataTable th { border: 1px solid #ddd; padding: 8px; } #dataTable tr:nth-child(even) { background-color: #f2f2f2; } #dataTable tr:hover { background-color: #ddd; } #dataTable th { padding-top: 12px; padding-bottom: 12px; text-align: left; background-color: rgb(211, 154, 80); color: white; }
View more
    
main.js
copy
const FOLDERID = {{"YOUR_FILE_STORE_FOLDER_ID"}}; //Enter your File Store Folder ID function uploadfile() { debugger; var x = document.getElementById("fileupload").files[0]; var filestore = catalyst.file; var folder = filestore.folderId(FOLDERID); var uploadPromise = folder.uploadFile(x).start(); uploadPromise.then((response) => { var FileID = response.content.id; var FileName = response.content.file_name; var UploadedTime = response.content.created_time; var FileSize = response.content.file_size; var WorkDriveSync = 'In Progress'; var details = [ { FileID, WorkDriveSync, FileName, UploadedTime, FileSize } ]; var datastore = catalyst.table; var table = datastore.tableId('WorkDriveFileID'); var insertPromise = table.addRow(details); insertPromise .then((response) => { setTimeout(function () { alert("File Uploaded Successfully"); }, 3000); window.location.reload(); }) .catch((err) => { console.log(err); alert(err) }); }).catch(err => { console.log(err); alert("Try again after Sometime"); }); } function getfiles() { catalyst.auth.isUserAuthenticated().then(result => { $.ajax({ url: "/server/files/getFiles", type: "GET", success: function (respData) { debugger; var data = getRequiredData(respData); renderTable(data); }, error: function (error) { alert(error.message); } }); }).catch(err => { document.body.innerHTML = 'You are not logged in. Please log in to continue. Redirecting you to the login page..'; setTimeout(function () { window.location.href = "login.html"; }, 3000); }); } function renderTable(respData) { debugger; var col = []; for (var i = 0; i < respData.length; i++) { for (var key in respData[i]) { if (col.indexOf(key)===-1) { col.push(key); } } } var table=document.createElement("table"); table.classList.add("ca-table-view"); table.setAttribute('id', 'dataTable' ); var tr=table.insertRow(-1); for (var i=0; i < col.length; i++) { var th=document.createElement("th"); th.innerHTML=col[i]; tr.appendChild(th); } for (var i=0; i < respData.length; i++) { tr=table.insertRow(-1); for (var j=0; j < col.length; j++) { var tabCell=tr.insertCell(-1); tabCell.innerHTML=respData[i][col[j]]; } } debugger; var divContainer=document.getElementById("filestore"); divContainer.innerHTML="" ; divContainer.appendChild(table); } function getRequiredData(data) { var i; var resp=[]; for (i=0; i < data.length; i++) { var displayData=data[i]; var gulp={ "File Name" : displayData.FileName, "Uploaded Time" : displayData.UploadedTime, "File Size" : displayData.FileSize, "Filestore Upload" : 'Completed' , "WorkDrive Sync" : displayData.WorkDriveSync, "
Download File
" : '
' } if (displayData.WorkDriveSync==="In Progress" ) { gulp["
Delete File
"] = '
🗑
' } else if (displayData.WorkDriveSync === "Completed") { gulp["
Delete File
"] = '
🗑
' } resp.push(gulp); } return resp; } function showAlert() { alert("WorkDrive Sync in Progress. Try Deleting the file Later.") } function logout() { var redirectURL = "{{YOUR_APP_DOMAIN}}/app/login.html"; //Enter the app domain of your project var auth = catalyst.auth; auth.signOut(redirectURL); } function showDeletePopup(fileID) { debugger; $('#ModalDanger').modal('show'); var deleteBtn = document.getElementById("delete-btn"); deleteBtn.value = fileID; } function deleteFile() { var fileID = document.getElementById('delete-btn').value; $.ajax({ url: "/server/files/deleteFile?fileID=" + fileID, type: "delete", success: function (data) { debugger; $('#ModalDanger').modal('toggle'); $("#myModalLabel").html("
Success"); $("#message").html("File Deleted Successfully"); $('#myModal').modal('show'); setTimeout(function () { location.reload(); }, 3000); }, error: function (error) { $("#myModalLabel").html("
Failure"); $("#message").html("Please try again after Sometime"); $('#myModal').modal('show'); } }); } function downloadfile(filedownloadid) { var filestore = catalyst.file; var folder = filestore.folderId(FOLDERID); var file = folder.fileId(filedownloadid); var downloadPromise = file.getDownloadLink(); downloadPromise .then((response) => { var url = response.content.download_url; const link = document.createElement('a'); link.href = url; link.style.display = 'none'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }) .catch((err) => { alert("Error downloading file. Please try again after some time"); }); }
View more

Next, create a new HTML file in the client/ directory and name it login.html. Add the code given below to the file.

    
login.html
copy
<html> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Catalyst File Vault</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <script src="main.js"></script> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <script src="https://js.zohostatic.com/catalystclient/1.0.0/catalystWebSDK.js"></script> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"> </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"> </script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"> </script> <script src="https://js.zohostatic.com/catalystclient/1.0.0/catalystWebSDK.js"></script> <script src="https://static.zohocdn.com/catalyst/sdk/js/2.0.0/catalystWebSDK.js"></script> <script src="/__catalyst/sdk/init.js"></script> <script> catalyst.auth.signIn("login"); </script> <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <style> #login { height: 260px; width: 500px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; } body { background-color: antiquewhite; } </style> <body> <center> <br><br><br> <h1 class="display-5">CATALYST FILESTORE ~ WORKDRIVE SYNC </h1><br> <h3>(Sync Between Catalyst Filestore and Zoho Workdrive)</h3> </center> <div id="login"></div> </body> </html>
View more

The client directory is now configured.

Let us quickly go through the working of the functions and the client of the application:

  • The login.html file in the client component enables Catalyst Authentication login. This does not handle the Zoho sign-in feature, only the Catalyst login.

  • index.html contains the code for the front-end of the client. The CSS is defined in main.css.

  • main.js: The JavaScript function in the client component that handles the various actions performed in the client through these functions:

    • uploadfile(): Initiates the file upload in the client. The file is uploaded to the File Store, and its metadata is populated. This metadata is inserted into the Data Store table after creating a new row. The WorkDrive sync status is set to “In Progress” with the file upload.

    • getfiles(): Sends a GET request to the /getFiles path defined in the Advanced I/O function that fetches the table rows from the Data Store. This is triggered automatically when the index page of the client is loaded.

    • renderTable(): Creates and renders a table in client which is populated with the response data of getfiles()

    • getRequiredData(): Fetches the metadata of each file from getfiles(), such as the name, size, File Store upload status, WorkDrive sync status to render in the client. This also renders the download and delete icons for each file.

    • deleteFile(): Sends a DELETE request to the /deleteFile path defined in the Advanced I/O function. The showDeletePopup() triggers a pop-up that confirms the delete action.

    Note: You will not be able to delete a file from the client while the WorkDrive sync is still in progress.
    • downloadfile(): Initiates the file download through a download promise when a download link is clicked

    • logout(): Logs the user out of the application

  • The Advanced I/O function defines the following APIs:

    • /getFiles: Queries the Data Store table using ZCQL to fetch its rows and sends the response to main.js

    • /deleteFile: This triggers an API to delete the file from WorkDrive through the PATCH method. The OAuth credentials are passed to authorize this action. The file is then deleted from the File Store and the associated record is removed from the Data Store as well. The response is sent to main.js which then renders the updated information in the client.

  • The Event function is triggered each time the event listener executes. This function performs the following actions:

    • Downloads the file that was sent in as the event data by the event listener using a file stream
    • Uploads the file and its metadata to WorkDrive through an API with the POST method. The OAuth credentials are passed to authorize this action.
    • If the action is successful, the Work Drive sync status is set to “Completed”. The record in the Data Store is updated with the WorkDrive file ID and the sync status.

Last Updated 2023-12-15 18:54:08 +0530 +0530