1/* This script is for myreports.html */ 2 3let bulkSharedReportsViewId = null; 4 5window.onload = function() { 6 try { 7 let actionToDo = Common.getURLParamValue("actionToDo"); 8 if (actionToDo != null && actionToDo == "recoverTodaysMeetings") { 9 Common.openReportRecoveryModal(RECOVER_REPORTS_POPUP_SOURCE_REPORT_GENERATION_FAILED); 10 let reason = Common.getURLParamValue("reason"); 11 if(reason !=null && reason && typeof(reason)=='string' && reason.length>0) { 12 LOGGER.log(Level.SEVERE,"Opened autoRecoverReportpopup with reason "+reason,null,reason); 13 } 14 } 15 16 // Pre processing before loaing my reports. 17 localStorage.setItem("googlemeet-attendance-tracker-ext-lastrefreshtime", new Date().getTime().toString()); // This was introduced during auto-backup...current not aware what purpose this is solving 18 bulkSharedReportsViewId = Common.getURLParamValue("vid"); 19 20 if (bulkSharedReportsViewId != null) { 21 // Being loaded for a user in shared reports view 22 executeScript(false); 23 } else { 24 // Actual user visiting myreports.html 25 // we should not use this inside window..so passing the first args as null for bind 26 let fastLoadCallbackFunc = executeScript.bind(null, true); 27 Common.bindAuthSession(handleMyReportsPageLoad, true, fastLoadCallbackFunc); 28 } 29 } catch (e) { 30 LOGGER.log(Level.SEVERE, "Exception while loading product page myreports.html", e); 31 } 32} 33 34function handleMyReportsPageLoad(user=null) { 35 try{ 36 // In future when user obj is needed..use it from the args and then if required reload the page again with executeScript and try to handle without passing the user obj to executeScript 37 }catch(e){ 38 LOGGER.log(Level.SEVERE,"Exception inside handleMyReportsPageLoad",e); 39 } 40} 41 42//global variables 43let attendanceReports; 44let classSelectedToSaveReport=""; 45let pageNumber = 1; 46let bulkReportsSelected = []; 47let isBulkSharedReportsView = false; 48 49async function executeScript(canInvokeAutoBackup=false) { 50 try{ 51 let contents = null; 52 let publicData = null; 53 if(bulkSharedReportsViewId!=null) { 54 Common.hideNavBarElementsForSharedView("BULK_SHARED_REPORTS", null); 55 let sharedData = (await Common.handleShareAction("GET_PUBLICID_DATA", bulkSharedReportsViewId, false)).data; 56 contents = sharedData.data; 57 publicData = sharedData.public_data; 58 isBulkSharedReportsView = true; 59 } else { 60 contents = localStorage.getItem("googlemeet-attendance-tracker-ext"); 61 } 62 if(contents!==null && contents!="[]") { 63 attendanceReports = JSON.parse(contents); 64 document.getElementById("reportCount").innerHTML = attendanceReports.length; 65 let usedStorage = Math.round(Number(attendanceReports.length/600)*100); 66 if(!isBulkSharedReportsView) { 67 let storageUseBarEle = document.getElementById("storageUseBar"); 68 if(storageUseBarEle!=null) { 69 storageUseBarEle.style.display = ""; 70 } 71 } 72 document.getElementById("progressBarValue").ariaValueNow = usedStorage; 73 document.getElementById("progressBarValue").style.width = `${usedStorage}%`; 74 let isRecoverReportFeatureEnabled = Common.isRecoverReportsFeatureEnabled();
75 let isSharedDataViewedByANewUser = isBulkSharedReportsView && Common.getLocalAttendanceReports()==null; 76 let tableHead = 77 ` 78 <div class="container-fluid"> 79 <div class="row justify-content-between"> 80 <div> 81 <h3>${isBulkSharedReportsView ? "Shared Meeting Reports," : "Your Recent Meetings,"}</h3> 82 </div> 83 <div class="float-right"> 84 <a href="https://chromewebstore.google.com/detail/google-meet-attendance-tr/ldjjokmalaidehbgbifihdfdondjgfha?hl=en&authuser=0" target="_blank" style="margin-right: 10px; text-decoration:none;"><img src="${isSharedDataViewedByANewUser ? "svg/extension.svg" : "svg/share.svg"}" ${isSharedDataViewedByANewUser ? 'height="22px;" width="22px"' : 'height="18px;" width="18px"'} style="margin-bottom:3px; margin-right: 3px;" /> ${isSharedDataViewedByANewUser ? "Install Google Meet Attendance Tracker" : "Refer us to your network" } 😊</a> 85 </div> 86 </div> 87 </div> 88 <!--Participants search box start--> 89 <nav class="navbar navbar-light bg-light" style="position: sticky; top: 72px;" id="myReportsNav"> 90 <div class="form-inline row"> 91 <input type="text" autocomplete="off" id="searchReport" onkeyup="searchReport()" class="form-control searchReport-placeholder" placeholder="Search by Meeting Name" aria-label="Username" aria-describedby="basic-addon1" style="width:260px; border-color: #979998; border-radius: 23px;"> 92 </div> 93 ${!isRecoverReportFeatureEnabled ? ` 94 <a href="backup.html" class="btn btn-info btn-sm ${isBulkSharedReportsView ? "notVisible" : ""}" style="margin-left: -15px; height: 36px;"> 95 <img src="svg/backup-restore.svg" style="margin-bottom: 0px; margin-right: 5px;" width="23px;" height="22px;" /> 96 Backup/Restore your data 97 </a> 98 99 ` : 100 ` 101 <button id="recoverReportButton" onclick="Common.openReportRecoveryModal()" class="btn-sm attention-btn ${isBulkSharedReportsView ? "notVisible" : ""}" style="display: flex; align-items: center; outline: none;"> 102 <img src="svg/thunder-white.svg" style="width:21px; height:21px; padding-left: 1px;" /> 103 <span style="padding-left: 3px; padding-right: 11px;">Recover past meeting</span> 104 </button> 105 106 `} 107 <a class="${isBulkSharedReportsView ? "notVisible" : ""}" style="text-decoration: none; margin-right: 100px; margin-left: 20px;" id="autoBackUpToggleElement" ><label style="margin-top: 16px" class="toggle"><input id="autoBackupToggleBtn" type="checkbox"><span class="slider"></span></label><span class="toggle-label"><b style="font-size: 17px;"> <span id="autoBackupToggleText">Auto Backup</span></b></span></a> 108 <a class="${isBulkSharedReportsView ? "notVisible" : ""}" style="margin-left: -110px; margin-right: 0px; color: #100d94" id="backupsuggestions"></a> 109 <div id="paginationSwitches" class="${isBulkSharedReportsView ? "notVisible" : ""}"> 110 <span id="paginationContent"></span> 111 112 <button id="paginationPrevious" class="btn btn-sm btn-outline-secondary" data-toggle="tooltip" title="" data-placement="top" > 113 <img src="svg/left-arrow.svg" /> 114 </button> 115 116 <button id="paginationNext" class="btn btn-sm btn-outline-secondary" data-toggle="tooltip" title="" data-placement="top"> 117 <img src="svg/right-arrow.svg" /> 118 </button> 119 </div> 120 </nav> 121 <div class="bg-light" id="bulkReportsSelectionActions" style="display: none; top: 72px; position: sticky; z-index: 1"> 122 <div class="container-fluid"> 123 <div class="row"> 124 125 <div style="margin-top: 26px; margin-right: 24px;"> 126 <h6> 127 <span id="numberOfReportsSelected"></span>
128 <span onclick="removeAllSelectedReports()" onmouseover="this.style.color='#F34A3F'" onmouseout="this.style.color='#F47368'" style="color: #F47368; text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 4px; cursor: pointer; "><img height="19px;" width="19px;" src="svg/red_cross.svg" />clear</span> 129 </h6> 130 </div> 131 132 <div id="verticalLineBlukActionsDivider" style="border-left: 1px solid lightgray;"></div> 133 134 <div style="margin-top: 20px; margin-left: 24px;"> 135 <button style="width: 110%;" type="button" class="btn btn-info" onclick='Common.handleShareAction("BULK_ATTENDANCE_REPORT",bulkReportsSelected,true)'> 136 Create link 137 <img src="svg/link.svg" height="22px;" width="22px;" /> 138 </button> 139 </div> 140 141 142 </div> 143 </div> 144 </div> 145 <!--Participants search box end--> 146 <table class="table table-hover" id="myReportsMainTable" style="margin-top: 10px;"> 147 <thead class="thead-dark" style="position: sticky; top: 140px;"> 148 <tr> 149 <th scope="col">S.No</th> 150 <th scope="col" class="text-center ${isBulkSharedReportsView ? "hidden" : ""}"> 151 <div style="visibility: hidden;"> 152 </div> 153 </th> 154 <th scope="col" style="width: 175px; max-width: 175px; white-space: nowrap; overflow: hidden; text-overflow: clip;" class="text-center">Meeting Name</th> 155 <th scope="col" class="text-center ${isBulkSharedReportsView ? "hidden" : ""}"> 156 <svg style="visibility: hidden;" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16"> <path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg> 157 </th> 158 <th scope="col" class="text-center">Meeting Date</th> 159 <th scope="col" class="text-center">Report Generated At</th> 160 <th scope="col" class="text-center">Meeting Duration</th> 161 <th scope="col" class="text-center ${isBulkSharedReportsView ? "hidden" : ""}">Share Report</th> 162 <th scope="col" class="text-center ${isBulkSharedReportsView ? "hidden" : ""}">Saved to Class</th> 163 <th scope="col" class="text-center">Total Participants</th> 164 <th scope="col" class="text-center">View Report</th> 165 <th scope="col" class="text-center ${isBulkSharedReportsView ? "hidden" : ""}">Delete Report</th> 166 </tr> 167 </thead> 168 <tbody style="font-size: 20px; display: none;" id="reportsTableBody"> 169 `; 170 let tableBody = ""; 171 let noReportsDisplayingTemplate = ` 172 <div id="noReportFound" class="container" style="display: none; margin-top: 20px;"> 173 <div class="text-center"> 174 <img src="svg/search.svg" style="height: 25px; width: 25px;" /> 175 <span> 176 <b style="margin-left: 8px;">Unable to find the report you are looking for?</b> 177 <p style="margin-top: 10px;"> 178 1. Try searching for it in the next / previous pages using the 179 <button class="btn btn-sm" > 180 <img src="svg/left-arrow.svg" /> 181 </button> 182 183 <button class="btn btn-sm"> 184 <img src="svg/right-arrow.svg" /> 185 </button> 186 buttons <i>(present in the middle right corner of the webpage)</i> 187 </p> 188 </span> 189 </div> 190 </div> 191 `; 192 let tableReportsLoadingTemplate = ` 193 <div id="tableReportsLoading" class="container-fluid" style="display: none;"> 194 <div class="text-center" style="margin-top: 20px;"> 195 <img src="myreports-skeleton.svg" style="width: 100%; height: 100%;"/> 196 <br/> 197 <img src="myreports-skeleton.svg" style="width: 100%; height: 100%;"/> 198 <br/> 199 <img src="myreports-skeleton.svg" style="width: 100%; height: 100%;"/> 200 </div> 201 </div> 202 `; 203 tableBody += "</tbody></table>"; 204 tableBody += noReportsDisplayingTemplate; 205 tableBody += tableReportsLoadingTemplate; 206 let tableReport = tableHead+tableBody; 207 // inserting table into myreports.html file 208 document.getElementById("reportDetails").innerHTML = tableReport; 209 // Inject the firstPage reports 210 injectCurrentPageReportsInUI(pageNumber, false); 211 // auto backup toggle button 212 document.getElementById("autoBackupToggleBtn").addEventListener("click",function(){ 213 let toggledAutoBackupMode = Common.toggleAutoBackupMode(); 214 if(toggledAutoBackupMode) { 215 setTimeout(function(){ 216 doAutoBackupFromMyReports(); 217 },350); 218 } 219 });
220 try{completeAutoBackupStatus()}catch(ex){LOGGER.log(Level.SEVERE,"Unable to complete autobackup status",ex); console.log("unable to toggle autobackup btn")}; 221 try{paginateNext()}catch(exx){LOGGER.log(Level.SEVERE,"Exception while trying to add pagination next click event listener",exx);} 222 try{paginatePrevious()}catch(exxx){LOGGER.log(Level.SEVERE,"Exception while trying to add pagination previous click event listener",exxx);} 223 if(canInvokeAutoBackup) { 224 doAutoBackupFromMyReports(); 225 } else { 226 showBackUpSuggestions(); 227 } 228 if(isBulkSharedReportsView) { 229 try{ 230 Common.trackPageViewsForViewID(bulkSharedReportsViewId); 231 Common.hideNavBarElementsForSharedView("BULK_SHARED_REPORTS", publicData); 232 Common.addPopovers(); 233 }catch(e){ 234 LOGGER.log(Level.SEVERE,"Exception while performing shared view specific changes",e); 235 } 236 } else { 237 Common.addPopovers(); 238 Common.trackNewAttendanceReportGeneration(); 239 } 240 } else { /* *********** Error HTML template *********** */ 241 document.getElementById("reportCount").innerHTML = "0"; 242 document.getElementById("progressBarValue").ariaValueNow = 0; 243 document.getElementById("progressBarValue").style.width = "0%"; 244 // report not found template 245 let reportNotFoundTemplate = 246 ` 247 <div class="text-center" style="margin-bottom: 20px;"> 248 <a href="backup.html" style="text-decoration:none;" class="btn btn-info"><img src="svg/restore-data.svg" width="22px;" height="22px;" style="margin-bottom: 3px; margin-right: 5px;"/>Restore your data</a> 249 </div> 250 <h3>Looks like you haven't tracked attendance using our chrome extension !</h3> 251 <p style="margin-top: 20px;">Incase if you feel something is wrong, please follow the below steps:</p> 252 <ol style="font-size: 18px;"> 253 <li>If you have a backup click <a href="backup.html" style="text-decoration:none;">here</a> to restore your data</li> 254 <li>Try refreshing this page</li> 255 <li>Read a quick tutorial of <a href="howtouse.html" style="text-decoration: none;">how to use</a> our chrome extension</li> 256 <li>Make sure you use the latest version of chrome browser</li> 257 <li>Do not close google meet tab without genearting the report using our chrome extension, learn more about this <a href="howtouse.html" style="text-decoration: none;">here</a></li> 258 <li>Make sure you computer is connected to internet</li> 259 <li>Make sure you have a high speed internet connection ( atleast 512kbps is recommended )</li> 260 <li>If you are unable to fix any issue please write your queries to: <a href="mailto:[email protected]">[email protected]</a> and <a href="mailto:[email protected]">[email protected]</a> (or) Create a ticket by <b><a href="contactus.html">Clicking here</a></b> </li> 261 </ol> 262 <p style="margin-top: 25px; font-size:20px;"><b>Note: </b>You will be seeing these error messages if you are not a user of our chrome extension</p> 263 `; 264 document.getElementById("reportDetails").innerHTML = reportNotFoundTemplate; 265 try{ 266 // If AutoBackup is enabled and there is no attendance reports in myreports then AutoBackup should be stopped. 267 if(Common.isAutoBackupEnabled()) { 268 localStorage.setItem("googlemeet-attendance-tracker-ext-autobackup",false); 269 } 270 }catch(e){ 271 LOGGER.log(Level.SEVERE,"Exception while turningoff autobackup for account which has no reports",e); 272 } 273 } 274 }catch(e){ 275 LOGGER.log(Level.SEVERE,"High Attention needed, Exception in loading and displaying reports in executebackupscript",e); 276 } 277} 278 279function injectCurrentPageReportsInUI(pageNumber, isAnimationRequired=false) { 280 try{ 281 let tableBody = ""; 282 document.getElementById("reportsTableBody").style.display = "none"; 283 document.getElementById("tableReportsLoading").style.display = "block"; 284 let fullAttendanceReportsCopy = JSON.parse(JSON.stringify(attendanceReports));
285 let currentPageReports = Common.getCurrentPageReports(pageNumber, fullAttendanceReportsCopy); 286 if(currentPageReports == null) { 287 LOGGER.log(Level.SEVERE,"Unable to inject reports in page",null,pageNumber,attendanceReports.length); 288 return; 289 } 290 let sNo = (SV.REPORTS_PER_PAGE * (pageNumber-1))+1; 291 const startNum = sNo; 292 let reportNum = startNum; 293 for(attendanceReport of currentPageReports) { 294 let reportCustomDefinitions = Common.getCustomDefinitions(attendanceReport); 295 let isHavingCustomMeetingName = reportCustomDefinitions.CUSTOM_MEETING_NAME; 296 let currMeetingName = isHavingCustomMeetingName ? attendanceReport.meetingName : attendanceReport.meetingCode; 297 let reportIdView = "report-"+String(reportNum)+"-view"; 298 let reportIdDelete = "report-"+String(reportNum)+"-delete"; 299 let reportIdEdit = "report-"+String(reportNum)+"-edit"; 300 let reportIdName = "report-"+String(reportNum)+"-name"; 301 let tableId = "table-"+String(reportNum)+"-id"; 302 let statusId = "status-"+String(reportNum)+"-id"; 303 let selectReportId = "select-"+String(reportNum)+"-report"; 304 // For statusHTML we will not read from currentPageReports because, currentPageReports will have only the current x - x+(per page reports) but reportNum will have value based on total attendanceReports count. 305 let statusHTML = attendanceReports[reportNum-1].joiningTime[0] == "reportAddedToClass" ? `<div id="${statusId}" style="color:green;"> <svg data-toggle="tooltip" data-placement="right" title="Succes: This report is added to a class" xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" class="bi bi-check-lg" viewBox="0 0 16 16"> <path d="M13.485 1.431a1.473 1.473 0 0 1 2.104 2.062l-7.84 9.801a1.473 1.473 0 0 1-2.12.04L.431 8.138a1.473 1.473 0 0 1 2.084-2.083l4.111 4.112 6.82-8.69a.486.486 0 0 1 .04-.045z"/> </svg> </div>` : `<div class="statusSymbol" id="${statusId}" style="cursor:pointer; color:#ff751f;"> <svg data-toggle="tooltip" data-placement="right" title="Pending: This report is not added to any of the class" xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" class="bi bi-exclamation-circle" viewBox="0 0 16 16"> <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/> <path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/> </svg> </div>` ; 306 let shareReportId = "shareReport-"+String(reportNum)+"-id"; 307 let shareReportHTML = `<div class="statusSymbol" id="${shareReportId}" style="cursor: pointer;" data-toggle="tooltip" data-placement="right" title="Share this report"><img src="svg/share-fill.svg" alt="share_icon"/></div>`; 308 let tableRecord = 309 ` 310 <tr id="${tableId}"> 311 <th scope="row">${sNo}</th> 312 <th class="text-center ${isBulkSharedReportsView ? "hidden" : ""}"><div><input style="cursor: pointer;" type="checkbox" id="${selectReportId}"></div></th> 313 <td class="text-center" style="max-width: 175px; white-space: nowrap; overflow: hidden; text-overflow: clip;" contenteditable="false" id="${reportIdName}">${currMeetingName}</td> 314 <td class="text-center ${isBulkSharedReportsView ? "hidden" : ""}" id="${reportIdEdit}" style="cursor:pointer"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16"> <path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg></td> 315 <td class="text-center">${attendanceReport.date}</td> 316 <td class="text-center">${attendanceReport.attendanceStopTime}</td> 317 <td class="text-center">${toTimeFormat(attendanceReport.meetingDuration)}</td> 318 <td class="text-center ${isBulkSharedReportsView ? "hidden" : ""}">${shareReportHTML}</td> 319 <td class="text-center ${isBulkSharedReportsView ? "hidden" : ""}"> ${statusHTML}</td> 320 <td class="text-center">${attendanceReport.studentNames.length}</td> 321 <td class="text-center"><button class="btn btn-sm btn-success" id="${reportIdView}">View Report</button></td> 322 <td class="text-center ${isBulkSharedReportsView ? "hidden" : ""}"><button class="btn btn-sm btn-danger" id="${reportIdDelete}">Delete Report</button></td> 323 </tr> 324 `; 325 tableBody += tableRecord; 326 reportNum += 1; 327 sNo += 1; 328 } 329 let tableReport = tableBody; 330 // inserting table into myreports.html file 331 document.getElementById("reportsTableBody").innerHTML = tableReport; 332 333 if(pageNumber == 1 || !isAnimationRequired) { 334 document.getElementById("tableReportsLoading").style.display = "none"; 335 document.getElementById("reportsTableBody").style.display = ""; 336 } else { 337 let loadingImageTime = pageNumber > 0 && pageNumber <= 2 ? 1200 : pageNumber == 3 ? 600 : 460; 338 setTimeout(function(){ 339 document.getElementById("tableReportsLoading").style.display = "none"; 340 document.getElementById("reportsTableBody").style.display = ""; 341 },loadingImageTime); 342 } 343 try{Common.addToolTips()}catch(toolTipsException){console.log("Unable to attach tooltips")} 344 345 //adding reportView and reportDelete functionalities 346 reportNum=startNum; 347 for(attendanceReport of currentPageReports) { 348 let reportIdView = "report-"+String(reportNum)+"-view"; 349 let reportIdDelete = "report-"+String(reportNum)+"-delete"; 350 let reportIdEdit = "report-"+String(reportNum)+"-edit"; 351 let statusId = "status-"+String(reportNum)+"-id"; 352 let selectReportId = "select-"+String(reportNum)+"-report"; 353 let shareReportId = "shareReport-"+String(reportNum)+"-id"; 354 document.getElementById(reportIdView).addEventListener("click",function(){ 355 viewReport(reportIdView); 356 }); 357 document.getElementById(reportIdDelete).addEventListener("click",function(){ 358 deleteReport(reportIdDelete); 359 }); 360 document.getElementById(reportIdEdit).addEventListener("click",function(){ 361 toggleEditMeetingName(reportIdEdit); 362 }); 363 document.getElementById(statusId).addEventListener("click",function(){ 364 let currReportNum = findReportNumber(statusId); 365 if(attendanceReports[currReportNum-1].joiningTime[0] != "reportAddedToClass") { 366 $("#statusUpdateModal").modal("toggle"); 367 fillModalBodyContents(statusId); 368 } 369 }); 370 document.getElementById(shareReportId).addEventListener("click",async function(){ 371 let currReportNum = findReportNumber(shareReportId); 372 await Common.handleShareAction("ATTENDANCE_REPORT",attendanceReports[currReportNum-1], true); 373 }); 374 document.getElementById(selectReportId).addEventListener("click",function(){ 375 handleBulkReportsSelectedActions(); 376 }); 377 reportNum += 1; 378 } 379 }catch(e){
380 LOGGER.log(Level.SEVERE,"Exception while injecting reports for current page - High priority",e); 381 } 382} 383 384function paginateNext() { 385 try{ 386 let paginateNextEle = document.getElementById("paginationNext"); 387 if(paginateNextEle != null) { 388 paginateNextEle.addEventListener("click", function(){ 389 resetSearchReport(); 390 injectCurrentPageReportsInUI(pageNumber+1, true); 391 pageNumber += 1; 392 Common.trackFeatureUsage(paginate_attendance_report); 393 }); 394 } 395 }catch(e){ 396 LOGGER.log(Level.SEVERE,"Exception inside paginateNext",e); 397 } 398} 399 400function paginatePrevious() { 401 try{ 402 let paginatePrevEle = document.getElementById("paginationPrevious"); 403 if(paginatePrevEle != null) { 404 paginatePrevEle.addEventListener("click",function(){ 405 resetSearchReport(); 406 injectCurrentPageReportsInUI(pageNumber-1, false); 407 pageNumber -= 1; 408 if(pageNumber<=1) { 409 pageNumber = 1; 410 } 411 }); 412 } 413 }catch(e){ 414 LOGGER.log(Level.SEVERE,"Exception inside paginatePrevious",e); 415 } 416} 417 418function resetSearchReport() { 419 try{ 420 let searchReportEle = document.getElementById("searchReport"); 421 if(searchReportEle != null) { 422 searchReportEle.value = ""; 423 if(!isBulkSharedReportsView) { 424 Common.removeReportNotFoundTemplateInMyReportsTableBody(); 425 } 426 } 427 }catch(e){ 428 LOGGER.log(Level.SEVERE,"Exception while resetting search",e); 429 } 430} 431 432function handleBulkReportsSelectedActions() { 433 try{ 434 let startReportNumForCurrentPage = (SV.REPORTS_PER_PAGE * (pageNumber-1))+1; 435 let endingReportNumForCurrentPage = startReportNumForCurrentPage+SV.REPORTS_PER_PAGE; 436 bulkReportsSelected = []; 437 for(let i=startReportNumForCurrentPage;i<=endingReportNumForCurrentPage;i++) { 438 try{ 439 let selectReportId = "select-"+String(i)+"-report"; 440 let reportCheckBoxEle = document.getElementById(selectReportId); 441 if(reportCheckBoxEle!=null) { 442 if(reportCheckBoxEle.checked) { 443 let reportNum = findReportNumber(selectReportId); 444 let checkedAttendanceReport = attendanceReports[reportNum-1]; 445 bulkReportsSelected.push(checkedAttendanceReport); 446 } 447 } 448 }catch(e){ 449 break; 450 } 451 } 452 if(bulkReportsSelected.length>0) { 453 let numberOfReportsSelectedEle = document.getElementById("numberOfReportsSelected"); 454 if(numberOfReportsSelectedEle!=null) { 455 numberOfReportsSelectedEle.innerHTML = `<b>${bulkReportsSelected.length}</b> ${bulkReportsSelected.length>1 ? "Reports" : "Report"} Selected.`; 456 let myReportsNav = document.getElementById("myReportsNav"); 457 if(myReportsNav!=null && myReportsNav.style.display!="none") { 458 let eleHeight = "62px"; 459 try{eleHeight = myReportsNav.getBoundingClientRect().height;eleHeight += "px";}catch(e){} 460 myReportsNav.style.display = "none"; 461 let bulkReportsSelectionActionsEle = document.getElementById("bulkReportsSelectionActions"); 462 if(bulkReportsSelectionActionsEle!=null) { 463 bulkReportsSelectionActionsEle.style.height = eleHeight; 464 let verticalLineBlukActionsDivider = document.getElementById("verticalLineBlukActionsDivider"); 465 if(verticalLineBlukActionsDivider!=null) { 466 verticalLineBlukActionsDivider.style.height = eleHeight; 467 $("#bulkReportsSelectionActions").fadeIn(200); 468 } 469 } 470 } 471 } 472 } else { 473 if(bulkReportsSelected.length == 0) { 474 let bulkReportsSelectionActionsEle = document.getElementById("bulkReportsSelectionActions"); 475 if(bulkReportsSelectionActionsEle!=null) { 476 let myReportsNav = document.getElementById("myReportsNav"); 477 if(myReportsNav!=null) { 478 bulkReportsSelectionActionsEle.style.display = "none"; 479 $("#myReportsNav").fadeIn(200); 480 } 481 } 482 } 483 } 484 }catch(e){ 485 LOGGER.log(Level.SEVERE,"Exception insied handleBulkReportsSelectedActions",e); 486 } 487} 488 489function removeAllSelectedReports() { 490 try{ 491 let startReportNumForCurrentPage = (SV.REPORTS_PER_PAGE * (pageNumber-1))+1; 492 let endingReportNumForCurrentPage = startReportNumForCurrentPage+SV.REPORTS_PER_PAGE; 493 for(let i=startReportNumForCurrentPage;i<=endingReportNumForCurrentPage;i++) {
494 try{ 495 let selectReportId = "select-"+String(i)+"-report"; 496 let reportCheckBoxEle = document.getElementById(selectReportId); 497 if(reportCheckBoxEle!=null) { 498 if(reportCheckBoxEle.checked) { 499 reportCheckBoxEle.checked = false; 500 } 501 } 502 }catch(e){ 503 break; 504 } 505 } 506 handleBulkReportsSelectedActions(); 507 }catch(e){ 508 LOGGER.log(Level.SEVERE,"Exception while removeAllSelectedReports",e); 509 } 510} 511 512 513// incase if a new report is added from another tab then the localStorage must be updated 514window.addEventListener("storage",function(e){ 515 try{ 516 let currentlyModifiedKey = typeof(e.key) == 'string' && e.key.length > 0 ? e.key : null; 517 if(currentlyModifiedKey != null) { 518 if(Common.isOurLocalStorageKey(currentlyModifiedKey)) { 519 if(!Common.isReRenderPopupShownToUser() && Common.isAnyModalOpenInCurrentPage()) { 520 if(currentlyModifiedKey == "googlemeet-attendance-tracker-ext") { 521 Common.checkAndClodsIfAnyModalIsOpen(); 522 Common.showReRenderPopup(); 523 } 524 } 525 setTimeout(function(){ 526 executeScript(false); 527 }, 500); 528 } 529 } 530 }catch(ere) { 531 LOGGER.log(Level.SEVERE,"Exception while re-render due to storage change",ere); 532 Common.showReRenderPopup(); 533 } 534}); 535 536//functions for deleting and viewing 537 538// view report 539function viewReport(attendanceReport) { 540 try{ 541 Common.removeClassName(attendanceReport, "onboard-effectBtn"); 542 Common.trackFeatureUsage(view_attendance_report_click); 543 let isReportFoundAndSetInSession = false; 544 reportId = findReportNumber(attendanceReport); 545 let currReportId = 1; 546 for(attendanceReport of attendanceReports) { 547 if(reportId==currReportId) { 548 x = []; 549 x.unshift(attendanceReport); 550 sessionStorage.clear("currReport-googlemeet-attendance-tracker-ext"); 551 sessionStorage.setItem("currReport-googlemeet-attendance-tracker-ext",JSON.stringify(x)); 552 console.log(currReportId); 553 isReportFoundAndSetInSession = true; 554 break; 555 } 556 currReportId += 1; 557 } 558 if(isReportFoundAndSetInSession) { 559 try { 560 let attendanceReportURL = "attendancereport.html"; 561 if(isBulkSharedReportsView) { 562 attendanceReportURL += "?vsrc=myreports"; 563 } 564 window.open(attendanceReportURL); 565 } catch(e) { 566 window.location.href = "attendancereport.html"; 567 } 568 } 569 }catch(e){ 570 LOGGER.log(Level.SEVERE,"Exception while trying to view report",e); 571 } 572} 573 574// delete report 575function deleteReport(attendanceReport) { 576 try{ 577 reportNum = findReportNumber(attendanceReport); 578 // deletig the object in localStorage 579 attendanceReports.splice((reportNum-1),1); 580 localStorage.setItem("googlemeet-attendance-tracker-ext",JSON.stringify(attendanceReports)); 581 // delete animations 582 let tableId = "#table-"+String(reportNum)+"-id"; 583 $(tableId).animate({right: "100%",opacity: "0%"},450,function(){ 584 executeScript(false); 585 }); 586 Common.trackFeatureUsage(attendance_report_deleted); 587 }catch(e){ 588 LOGGER.log(Level.SEVERE,"Exception while deleting a attendance report",e); 589 } 590} 591 592// change report name 593function toggleEditMeetingName(attendanceReport) { 594 try{ 595 let reportNum = findReportNumber(attendanceReport); 596 let reportCustomDefinitions = Common.getCustomDefinitions(attendanceReports[reportNum-1]); 597 let isHavingCustomMeetingName = reportCustomDefinitions.CUSTOM_MEETING_NAME; 598 let reportEditId = "report-"+String(reportNum)+"-edit"; 599 let reportName = "report-"+String(reportNum)+"-name";
600 let currState = document.getElementById(reportName).contentEditable; 601 if(currState==="true") { 602 let newMeetingName = document.getElementById(reportName).innerText.trim(); 603 if(newMeetingName && newMeetingName.length > 0) { 604 document.getElementById(reportName).contentEditable = false; 605 if(isHavingCustomMeetingName) { 606 attendanceReports[reportNum-1].meetingName = newMeetingName; 607 } else { 608 attendanceReports[reportNum-1].meetingCode = newMeetingName; 609 } 610 localStorage.setItem("googlemeet-attendance-tracker-ext",JSON.stringify(attendanceReports)); 611 document.getElementById(reportEditId).innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pencil" viewBox="0 0 16 16"> <path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg>`; 612 Common.trackFeatureUsage(report_name_changed); 613 } else { 614 alert("Meeting Name cannot be empty"); 615 document.getElementById(reportName).focus(); 616 } 617 } else { 618 document.getElementById(reportName).contentEditable = true; 619 document.getElementById(reportEditId).innerHTML = `<b style="font-size:14px;color:green">save</b>`; 620 document.getElementById(reportName).focus(); 621 } 622 }catch(e){ 623 LOGGER.log(Level.SEVERE,"Exception while editing meeting name",e); 624 } 625} 626 627 628// searches Report 629function searchReport() { 630 try { 631 let reportName = document.getElementById("searchReport").value.toUpperCase().trim(); 632 if(reportName != null && typeof(reportName)=='string') { 633 let tableRows = document.getElementsByTagName("tr"); 634 for(let i=1; i<tableRows.length; i++) { 635 let tableData = tableRows[i].getElementsByTagName("td")[0].innerHTML.toUpperCase(); 636 if(tableData.includes(reportName)) { 637 tableRows[i].style.display = ""; 638 } else { 639 tableRows[i].style.display = "none"; 640 } 641 } 642 if(reportName.trim() != "" && reportName.length > 0) { 643 if(!isBulkSharedReportsView) { 644 Common.addNoReportFoundTemplateInMyReportsTableBody(); 645 } 646 } else if(reportName === "") { 647 if(!isBulkSharedReportsView) { 648 Common.removeReportNotFoundTemplateInMyReportsTableBody(); 649 } 650 } 651 } 652 }catch(e){ 653 LOGGER.log(Level.SEVERE,"Exception while searching attendance report",e); 654 } 655} 656 657 658// modal body contents 659function fillModalBodyContents(attendanceReport) { 660 try{ 661 classSelectedToSaveReport = ""; 662 let reportNum = findReportNumber(attendanceReport); 663 let selectedMeetingData = attendanceReports[reportNum-1]; 664 console.log(selectedMeetingData) 665 let classData = JSON.parse(localStorage.getItem("googlemeet-attendance-tracker-ext-class")); 666 if(classData == null) { 667 /** 668 * When the classData is null it means user has never accessed myclasses.html, 669 * In below flow we will iterave over the classData, if it is null then it will create exception...so making it as empty array 670 */ 671 classData = []; 672 } 673 let modalBodyHTML = 674 ` 675 <div class="row"> 676 <div class="col-6"> 677 <p style="font-size: 14px;">S.No: <b>${reportNum}</b></p> 678 </div> 679 <div class="col-6"> 680 <p style="font-size: 14px; max-width: 200px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">Meeting Name: <b>${selectedMeetingData.meetingCode}</b></p> 681 </div> 682 <div class="col-6"> 683 <p style="font-size: 14px;">Meeting Date: <b>${selectedMeetingData.date}</b></p> 684 </div> 685 <div class="col-6"> 686 <p style="font-size: 14px;">Report Generated At: <b>${selectedMeetingData.attendanceStopTime}</b></p> 687 </div> 688 <div class="col-6"> 689 <p style="font-size: 14px;">Meeting Duration: <b>${toTimeFormat(selectedMeetingData.meetingDuration)}</b></p> 690 </div> 691 <div class="col-6"> 692 <p style="font-size: 14px;">Total Participants: <b>${selectedMeetingData.studentNames.length}</b></p> 693 </div> 694 </div> 695 <hr /> 696 <div class="row"> 697 <div class="col-5"> 698 <p style="font-size: 18px; font-weight: 450;">Save this report to: </p> 699 </div> 700 <div class="col-7"> 701 <select class="custom-select" onchange="updateClassSelectedToSaveReport()" id="classSelectedInStatusUpdate" > 702 <option disabled selected value>Click here to select a class</option> 703 `; 704 let atleastOneClassIsPresent = false; 705 try{ 706 for(classRecord of classData) { 707 let isDuplicateClass = Common.isDuplicateClass(classRecord); 708 let currRecordHTML = `<option ${isDuplicateClass ? "disabled" : ""}>${classRecord.className} ${isDuplicateClass ? "(inactive)" : ""}</option>`; 709 modalBodyHTML += currRecordHTML; 710 atleastOneClassIsPresent = true; 711 } 712 } catch(error){ 713 // do nothing
714 LOGGER.log(Level.SEVERE,"Exception while filling modal contents for modal in which we allow saving report to a class",error); 715 } 716 modalBodyHTML += 717 `</select> 718 </div> 719 </div> 720 <br/> 721 <p id="statusUpdateModalErrorMessage"></p> 722 <hr /> 723 <div class="text-center" id="statusUpdateModalFooter"> 724 <p style="font-size: 14px;" class="float-left">click <a href="myclasses.html" style="text-decoration: none;">here</a> to create a new class</p> 725 <button type="button" style="max-width: 240px; white-space: nowrap; overflow: hidden; text-overflow: clip;" class="btn btn-info float-right" id="statusUpdateModalSaveButton">Save</button> 726 </div> 727 `; 728 if(atleastOneClassIsPresent) { 729 document.getElementById("statusUpdateModalBody").innerHTML = modalBodyHTML; 730 document.getElementById("statusUpdateModalSaveButton").addEventListener("click",function(){ 731 saveReportToSelectedClass(selectedMeetingData, reportNum); 732 }); 733 document.getElementById("statusUpdateModalSaveButton").innerHTML = `Save`; 734 } else { 735 let noClassesFoundTemplate = 736 ` 737 <p>You haven't created a class yet !</p> 738 <ul style="line-height: 1.9"> 739 <li>Create a class to manage attendance class wise</li> 740 <li>Creating a class helps you find absentees after generating a report every time</li> 741 </ul> 742 <p>Click the below <i><u>Create class </u></i> button to get started.</p> 743 <div class="text-center p-1"> 744 <a href="myclasses.html" style="text-decoration:none;"><button style="margin-bottom: 10px; margin-top:10px; letter-spacing: 1px; font-size: 18px;" class="btn btn-info btn-block">Create class</button></a> 745 </div> 746 `; 747 document.getElementById("statusUpdateModalTitle").innerHTML = "No classes found !"; 748 document.getElementById("statusUpdateModalBody").innerHTML = noClassesFoundTemplate; 749 } 750 }catch(e){ 751 LOGGER.log(Level.SEVERE,"Exception while filling modal body contents -> savereporttoaclass modal",e); 752 } 753} 754 755// updates the class selected to save the report 756function updateClassSelectedToSaveReport() { 757 try{ 758 classSelectedToSaveReport = classSelectedInStatusUpdate.value; 759 document.getElementById("statusUpdateModalSaveButton").innerHTML = `Save to " ${classSelectedToSaveReport} "`; 760 }catch(e){ 761 LOGGER.log(Level.SEVERE,"Exception in updateClassSelectedToSaveReport",e); 762 } 763} 764 765 766// saves the selected report to the selected class 767function saveReportToSelectedClass(attendanceReport, reportNum) { 768 try{ 769 if(classSelectedToSaveReport=="") { 770 document.getElementById("statusUpdateModalErrorMessage").style.color = "red"; 771 document.getElementById("statusUpdateModalErrorMessage").innerHTML = "*Error: Select a class from the drop down and try again"; 772 } else { 773 document.getElementById("statusUpdateModalErrorMessage").style.color = "green"; 774 document.getElementById("statusUpdateModalErrorMessage").innerHTML = "success"; 775 let classData = JSON.parse(localStorage.getItem("googlemeet-attendance-tracker-ext-class")); 776 let classRecordFound = false; 777 let classRecordIndex = -1; 778 for(let index=0; index<classData.length; index++) { 779 let classRecord = classData[index]; 780 if(classRecord.className == classSelectedToSaveReport && !Common.isDuplicateClass(classRecord)) { 781 // saving data to class 782 classRecordIndex = index; 783 let studentsRawData = classRecord.studentsData; 784 studentsRawData = [...new Set(studentsRawData)]; // Fix to avoid duplicate participants names (for report generated via addon) -> We gave 2 present's for users will same name 785 let studentNamesFromRaw = []; 786 let studentAttendedPeriods = []; 787 let len = 0; 788 // extracting data from class by splitting name and attended periods based on hyphen 789 for(studentRawData of studentsRawData) { 790 let hyphenIndex = studentRawData.lastIndexOf("-"); 791 studentNamesFromRaw[len] = studentRawData.substring(0,hyphenIndex); 792 studentAttendedPeriods[len] = Number(studentRawData.substring(hyphenIndex+1)); 793 len++; 794 } 795 // giving attendance for current report present students 796 let attendees = attendanceReport.studentNames; 797 for(attendee of attendees) { 798 if(studentNamesFromRaw.includes(attendee)) { 799 let ind = studentNamesFromRaw.indexOf(attendee); 800 studentAttendedPeriods[ind] += 1; 801 } else { 802 studentNamesFromRaw.push(attendee); 803 studentAttendedPeriods.push(1); 804 len++; 805 } 806 } 807 let updatedStudentsRawData = []; 808 for(let i=0; i<len; i++) { 809 updatedStudentsRawData.push((studentNamesFromRaw[i]+"-"+studentAttendedPeriods[i])); 810 } 811 // sort it here 812 updatedStudentsRawData.sort(); 813 classData[classRecordIndex].studentsData = updatedStudentsRawData; 814 classData[classRecordIndex].totalReportsAdded = classData[classRecordIndex].totalReportsAdded+1; 815 let date = new Date(); 816 let dd = date.getDate();
817 let mm = date.toLocaleString('default', { month: 'short' }) 818 let yyyy = date.getFullYear(); 819 date = dd+"-"+mm+"-"+yyyy; 820 classData[classRecordIndex].lastReportAddedOn = date+" at "+new Date().toLocaleTimeString(); 821 localStorage.setItem("googlemeet-attendance-tracker-ext-class",JSON.stringify(classData)); 822 attendanceReports[reportNum-1].joiningTime[0] = "reportAddedToClass"; 823 localStorage.setItem("googlemeet-attendance-tracker-ext",JSON.stringify(attendanceReports)); 824 document.getElementById("statusUpdateModalErrorMessage").style.color = "green"; 825 document.getElementById("statusUpdateModalErrorMessage").innerHTML = "success"; 826 console.log(classData[classRecordIndex]) 827 executeScript(false); 828 classRecordFound = true; 829 classSelectedToSaveReport = ""; 830 $("#statusUpdateModal").modal("toggle"); 831 // sweet alert if needed -> goes here 832 Common.trackFeatureUsage(report_added_to_class); 833 break; 834 } 835 } 836 if(!classRecordFound) { 837 document.getElementById("statusUpdateModalErrorMessage").style.color = "red"; 838 document.getElementById("statusUpdateModalErrorMessage").innerHTML = `Something went wrong ! please close this popup and try again (or) <span style="color: blue; cursor: pointer; text-decoration: underline" onclick="Common.handleContactSupport(true)">Contact support</span>`; 839 } 840 } 841 }catch(e){ 842 LOGGER.log(Level.SEVERE,"Exception while saving report to the selected class",e); 843 } 844} 845 846function showBackUpSuggestions(showLoading) { 847 try{ 848 let lastBackUpTimeInMillis = Number(localStorage.getItem("googlemeet-attendance-tracker-ext-lastbackuptime")); 849 let suggestion = ""; 850 let suggestionTextColor = ""; 851 if(showLoading) { 852 suggestion = `<img style="margin-left: 140px; margin-right: 60px;" src="svg/loading-dots.svg">`; 853 suggestionTextColor = "#013485"; 854 fillBackUpSuggestions(suggestion, suggestionTextColor, false); 855 } 856 else if(!isNaN(lastBackUpTimeInMillis) && lastBackUpTimeInMillis == 0) { 857 suggestion = "<b>Hint: Make a backup of your data frequently</b>"; 858 suggestionTextColor = "#013485"; 859 fillBackUpSuggestions(suggestion, suggestionTextColor, true); 860 } else if(!isNaN(lastBackUpTimeInMillis) && lastBackUpTimeInMillis!=0 && lastBackUpTimeInMillis > 0) { 861 let currentTimeInMillis = new Date().getTime(); 862 let diffDaysCount = Math.floor((currentTimeInMillis-lastBackUpTimeInMillis)/(24*60*60*1000)); 863 if(diffDaysCount == 0) { 864 let lastBackUpTime = toTimeFormat(Math.floor((currentTimeInMillis-lastBackUpTimeInMillis)/1000)); 865 suggestion = `<b>Your Last Backup was made ${lastBackUpTime} ago</b>`; 866 suggestionTextColor = "green"; 867 fillBackUpSuggestions(suggestion, suggestionTextColor, false); 868 } else { 869 suggestion = diffDaysCount==1 ? `<b>Your last backup was made ${diffDaysCount} day ago</b>` : `<b>Caution: Your last backup was made ${diffDaysCount} days ago !</b>`; 870 suggestionTextColor = diffDaysCount==1 ? "#ff751f" : "red"; 871 fillBackUpSuggestions(suggestion, suggestionTextColor, true); 872 } 873 } 874 875 }catch(excep) { 876 LOGGER.log(Level.SEVERE,"Something went wrong inside showbackup suggestions",excep); 877 console.log("Something went wrong !"); 878 } 879} 880 881function fillBackUpSuggestions(suggestion, suggestionTextColor, isBlinkEffectNeeded) { 882 try{ 883 if(isBackupSuggestionsPresentInDom()) { 884 document.getElementById("backupsuggestions").innerHTML = suggestion; 885 document.getElementById("backupsuggestions").style.color = suggestionTextColor; 886 if(isBlinkEffectNeeded) { 887 setTimeout(function(){ 888 let blinkCount = 1; 889 let blinkInterval = setInterval(function(){ 890 if(isBackupSuggestionsPresentInDom()) { 891 if(blinkCount%2 == 0) { 892 if(isBackupSuggestionsPresentInDom()) { 893 document.getElementById("backupsuggestions").innerHTML = suggestion; 894 document.getElementById("backupsuggestions").style.color = suggestionTextColor; 895 } 896 } else { 897 if(isBackupSuggestionsPresentInDom()) { 898 document.getElementById("backupsuggestions").innerHTML = suggestion; 899 document.getElementById("backupsuggestions").style.color = "#f8f9fa"; 900 } 901 } 902 blinkCount += 1; 903 if(blinkCount > 5) { 904 if(isBackupSuggestionsPresentInDom()) { 905 document.getElementById("backupsuggestions").innerHTML = suggestion; 906 document.getElementById("backupsuggestions").style.color = suggestionTextColor; 907 } 908 clearInterval(blinkInterval); 909 } 910 } 911 },100); 912 },750); 913 } 914 } 915 }catch(exce) {
916 LOGGER.log(Level.SEVERE,"Somewhing went wrong while filling autobackup suggestions",exce); 917 console.log("Something went wrong !"); 918 } 919} 920 921function doAutoBackupFromMyReports() { 922 try{ 923 if(Common.isAutoBackupEnabled() && !Common.isSharedView()) { 924 showBackUpSuggestions(true); 925 Common.performAutoBackup(); 926 } else { 927 showBackUpSuggestions(); 928 } 929 }catch(e){ 930 LOGGER.log(Level.SEVERE,"Exception in doAutoBackupFromMyReports",e); 931 } 932} 933 934function isBackupSuggestionsPresentInDom() { 935 /** 936 * The reason for this method and this checks inside code is because, for some browsers backupsuggestions dom is being null 937 * due to very fastly manipulating the dom for blink effect animation every 100 milliseconds. 938 */ 939 try{ 940 let backupSuggestionsDom = document.getElementById("backupsuggestions").innerHTML; 941 return backupSuggestionsDom != null ? true : false; 942 }catch(e){ 943 // Dont push logs to server -> It will be dumped...some users in some browser there is issue when using setInterval in in very high frequency 944 return false; 945 } 946 return false; 947} 948 949function completeAutoBackupStatus() { 950 try { 951 let localDataForAutoBackUpStatus = localStorage.getItem("googlemeet-attendance-tracker-ext-autobackup"); 952 if(localDataForAutoBackUpStatus == null) { 953 localStorage.setItem("googlemeet-attendance-tracker-ext-autobackup",false); 954 } 955 let status = localStorage.getItem("googlemeet-attendance-tracker-ext-autobackup") === "true"; 956 let autoBackupToggleEle = document.getElementById("autoBackupToggleBtn"); 957 if(autoBackupToggleEle!=null) { 958 autoBackupToggleEle.checked = status; 959 status ? Common.changeAutoBackupToggleMessage("Auto Backup (enabled)") : Common.changeAutoBackupToggleMessage("Auto Backup (disabled)"); 960 } 961 }catch(e) { 962 LOGGER.log(Level.SEVERE,"Something went wrong inside completeAutoBackupStatus",e); 963 console.log("completeautobackup api failed due to"+e); 964 } 965} 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981// ## Common API's. Don't write business logic code below this line 982 983// finds the reportId from button id 984function findReportNumber(attendanceReport) { 985 report = attendanceReport.split("-"); 986 return Number(report[1]); 987} 988 989// to time hh:mm:ss format 990function toTimeFormat(time) 991{ 992 hh = Math.floor(time/3600); 993 time = time - (hh*3600); 994 mm = Math.floor(time/60); 995 time = time - (mm*60); 996 ss = time; 997 if(hh==0)return mm+" min "+ss+"s"; 998 else return hh+" hr "+mm+" min "+ss+"s"; 999} 1000 1001 1002// new version #1
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.