!DOCTYPE html html lang=en class=dark head meta charset=UTF-8 meta name=viewport content=width=device-width, initial-scale=1.0 titleWeb Dashboardtitle script src=httpscdn.tailwindcss.comscript !-- Screen Capture Library -- script src=httpshtml2canvas.hertzen.comdisthtml2canvas.min.jsscript script tailwind.config = { darkMode 'class', } script link rel=stylesheet href=httpscdnjs.cloudflare.comajaxlibsfont-awesome6.4.0cssall.min.css style --- GLOBAL STYLES --- root { --sb-track #e5e7eb; --sb-thumb #9ca3af; } .dark { --sb-track #2d2d2d; --sb-thumb #555; } Custom Scrollbar -webkit-scrollbar { width 8px; height 8px; } -webkit-scrollbar-track { background var(--sb-track); } -webkit-scrollbar-thumb { background var(--sb-thumb); border-radius 4px; } -webkit-scrollbar-thumbhover { background #777; } .no-scrollbar-webkit-scrollbar { display none; } .no-scrollbar { -ms-overflow-style none; scrollbar-width none; } Loader .spinner { border 3px solid rgba(255,255,255,0.1); border-radius 50%; border-top 3px solid #3b82f6; width 24px; height 24px; animation spin 1s linear infinite; } @keyframes spin { 0% { transform rotate(0deg); } 100% { transform rotate(360deg); } } Gradient Text for Icons .google-icon-gradient { background linear-gradient(45deg, #4285F4, #EA4335, #FBBC05, #34A853); -webkit-background-clip text; -webkit-text-fill-color transparent; background-clip text; } Active Tool Button Style .tool-btn.active { background-color #eff6ff; border-color #3b82f6; box-shadow 0 0 0 1px #3b82f6; } .dark .tool-btn.active { background-color #172554; border-color #60a5fa; box-shadow 0 0 0 1px #60a5fa; } SNIPPET TOOL STYLES #snippet-overlay { cursor crosshair; } #selection-box { border 2px dashed #3b82f6; background-color rgba(59, 130, 246, 0.2); position absolute; z-index 210; } Toast Animation @keyframes fade-in-out { 0% { opacity 0; transform translateY(20px) translateX(-50%); } 10% { opacity 1; transform translateY(0) translateX(-50%); } 90% { opacity 1; transform translateY(0) translateX(-50%); } 100% { opacity 0; transform translateY(-20px) translateX(-50%); } } .toast-msg { animation fade-in-out 3s forwards; } Mask Fade for scrollable areas .mask-fade { mask-image linear-gradient(to right, black 95%, transparent 100%); -webkit-mask-image linear-gradient(to right, black 95%, transparent 100%); } style head body class=bg-gray-50 text-gray-800 darkbg-gray-900 darktext-gray-200 h-screen w-screen flex flex-col overflow-hidden font-sans transition-colors duration-200 !-- HEADER BAR -- div class=h-12 bg-gray-200 darkbg-gray-950 border-b border-gray-300 darkborder-gray-800 flex items-center justify-between px-4 select-none z-40 shadow-sm flex-shrink-0 div class=flex items-center gap-2 font-bold text-gray-700 darktext-gray-200 i class=fa-solid fa-globe text-blue-500i spanWeb Dashboardspan div div class=flex items-center px-2 button onclick=toggleTheme() class=text-gray-500 hovertext-orange-500 darktext-gray-400 darkhovertext-yellow-300 transition text-sm p-2 rounded-full hoverbg-gray-300 darkhoverbg-gray-800 title=Toggle Theme i class=fa-solid fa-moon darkhiddeni i class=fa-solid fa-sun hidden darkinlinei button div div !-- MAIN CONTENT AREA -- div class=flex-1 flex flex-col relative overflow-hidden bg-gray-100 darkbg-gray-900 !-- WEB TOOLBAR -- div class=h-14 bg-white border-b border-gray-200 darkbg-gray-800 darkborder-gray-700 flex items-center px-4 select-none z-30 shadow-sm flex-shrink-0 overflow-x-auto no-scrollbar div class=flex items-center gap-2 w-max pr-2 !-- 1. CAPTURE & PRINT -- button onclick=activateSnipMode(this) id=btn-screenshot-web class=tool-btn text-xs bg-gray-800 hoverbg-gray-900 text-white border border-gray-600 darkbg-gray-100 darktext-gray-900 darkhoverbg-gray-200 px-3 py-2 rounded transition flex-shrink-0 title=Snip & Copy i class=fa-solid fa-camerai button button onclick=window.print() class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 text-gray-700 darktext-white px-3 py-2 rounded transition flex-shrink-0 title=Print Page i class=fa-solid fa-printi button div class=h-6 w-px bg-gray-300 darkbg-gray-600 mx-2 flex-shrink-0div !-- 2. GENERAL APPS -- button onclick=loadWebUrl('httpswww.google.comwebhpigu=1', 'Google Search', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Google i class=fa-brands fa-google google-icon-gradient text-smi button button onclick=loadWebUrl('httpsquillbot.comtranslateenglish-to-tamil', 'Translate', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Translate i class=fa-solid fa-robot text-green-600 text-smi button div class=h-6 w-px bg-gray-300 darkbg-gray-600 mx-2 flex-shrink-0div !-- 3. MAP TOOLS GROUP -- button onclick=loadWebUrl('httpsmaps.google.commapsq=Tiruchirappalli,+Tamil+Nadu&output=embed', 'Google Maps', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Google Maps i class=fa-solid fa-map-location-dot text-green-600 darktext-green-500 text-smi button button onclick=loadWebUrl('httpswww.mappls.complace-Tiruchirappalli-Tamil+Nadu-2uoxau@,,,l,f,f,f,f,f,f,zdata=MTAuODA3NjMrNzguNjk0MzQ5KzEzKzJ1b3hhdSsrMTQrKytNOTctRkxLLVRGMzYed', 'Mappls Map', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Mappls i class=fa-solid fa-location-dot text-orange-600 text-smi button button onclick=loadWebUrl('httpswww.openstreetmap.orgsearchquery=Tiruchirappalli', 'Open Street Map', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Open Street Map i class=fa-solid fa-map text-green-600 text-smi button button onclick=loadWebUrl('httpsbhuvan.nrsc.gov.inngmapsmode=Hybrid#4.3922.9182.78', 'Bhuvan', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Bhuvan i class=fa-solid fa-satellite text-indigo-600 text-smi button button onclick=loadWebUrl('httpstngis.tnega.orggeneric_viewer#', 'TN GIS', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=TN GIS i class=fa-solid fa-layer-group text-blue-500 text-smi button button onclick=loadWebUrl('httpstngis.tn.gov.inappsgi_viewer', 'Tamil Nilam GL Viewer', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Tamil Nilam i class=fa-solid fa-gopuram text-orange-600 text-smi button div class=h-6 w-px bg-gray-300 darkbg-gray-600 mx-2 flex-shrink-0div !-- 4. UTILITY TOOLS -- button onclick=loadWebUrl('httpswww.online-qrcode-generator.com', 'QR Generator', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=QR Gen i class=fa-solid fa-qrcode text-gray-800 darktext-white text-smi button button onclick=loadWebUrl('httpsclip.tn.gov.inclipindex.html', 'TN CLIP', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=TN CLIP i class=fa-solid fa-paperclip text-gray-500 darktext-gray-300 text-smi button div class=h-6 w-px bg-gray-300 darkbg-gray-600 mx-2 flex-shrink-0div !-- 5. GOVT SERVICES -- button onclick=loadWebUrl('httpswww.tnebnet.orgawplogin', 'Electricity Board', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=TNEB i class=fa-solid fa-bolt text-yellow-500 text-smi button !-- TNREGINET - Changed to openPopup -- button onclick=openPopup('httpstnreginet.gov.inportalwebHPrequestType=ApplicationRH&actionVal=homePage&screenId=114&UserLocaleID=en&_csrf=b32a71fc-a21b-4cc7-9e83-54774b604711', 'TNREGINET') class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=TNREGINET (Popup) i class=fa-solid fa-landmark text-green-700 darktext-green-400 text-smi button button onclick=loadWebUrl('httpseservices.tn.gov.ineservicesnewindex.html', 'E-Services', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=E-Services i class=fa-solid fa-laptop-file text-teal-600 text-smi button button onclick=loadWebUrl('httpsvptax.tnrd.tn.gov.inprojectformsVillagePanchayatMasterReceipt_Bill_Details.php', 'Village Tax', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Village Tax i class=fa-solid fa-house-flag text-green-700 text-smi button button onclick=loadWebUrl('httpstnurbanepay.tn.gov.inPT_AssessmentViewsLink.aspx#', 'Urban Tax', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Urban Tax i class=fa-solid fa-city text-blue-600 text-smi button button onclick=loadWebUrl('httpstrichymasterplan.comproposed-landuse', 'Trichy Master Plan', event) class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Master Plan i class=fa-solid fa-city text-orange-500 text-smi button div class=h-6 w-px bg-gray-300 darkbg-gray-600 mx-2 flex-shrink-0div !-- 6. GOOGLE SUITE & CLOUD (Opens in Detached Popup Window) -- button onclick=openPopup('httpswww.google.commaps', 'Google Maps') class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Google Maps i class=fa-solid fa-map-location-dot text-green-600 text-smi button button onclick=openPopup('httpscalendar.google.comcalendar', 'Google Calendar') class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Google Calendar i class=fa-regular fa-calendar-days text-blue-600 text-smi button button onclick=openPopup('httpsclassroom.google.com', 'Google Classroom') class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Google Classroom i class=fa-solid fa-chalkboard-user text-green-600 text-smi button button onclick=openPopup('httpsmail.google.comchatu0#chathome', 'Google Chat') class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Google Chat i class=fa-regular fa-comments text-green-600 text-smi button button onclick=openPopup('httpskeep.google.com', 'Google Keep') class=tool-btn text-xs bg-white border border-gray-300 hoverbg-gray-50 darkbg-gray-700 darkborder-gray-600 darkhoverbg-gray-600 px-3 py-2 rounded transition flex-shrink-0 title=Google Keep i class=fa-regular fa-lightbulb text-yellow-500 text-smi button div class=h-6 w-px bg-gray-300 darkbg-gray-600 mx-2 flex-shrink-0div !-- 7. CONTROLS -- button onclick=clearWebWorkspace() class=text-xs bg-red-600 hoverbg-red-700 text-white px-3 py-2 rounded transition flex-shrink-0 title=Clear Workspace i class=fa-solid fa-trashi button div div !-- MAIN FRAME CONTAINER -- div class=flex-1 relative bg-gray-100 darkbg-gray-900 overflow-hidden flex flex-col !-- URL BAR -- div class=h-8 bg-gray-200 darkbg-gray-950 flex items-center px-2 gap-2 text-xs border-b border-gray-300 darkborder-gray-800 span class=text-gray-500 font-boldURLspan input type=text id=url-display readonly class=flex-1 bg-transparent text-gray-700 darktext-gray-300 outline-none truncate placeholder=Select a tool above... !-- REFRESH BUTTON -- button onclick=refreshWebPage() id=btn-refresh class=text-gray-600 hovertext-blue-600 darktext-gray-400 darkhovertext-blue-400 hidden px-2 title=Refresh Page i class=fa-solid fa-rotate-righti button button onclick=openCurrentInNewTab() id=btn-newtab class=text-blue-600 hoverunderline hidden border-l border-gray-400 darkborder-gray-700 pl-2Open in New Tabbutton div iframe id=web-frame class=flex-1 w-full border-0 bg-white src=aboutblankiframe !-- Placeholder when empty -- div id=empty-placeholder class=absolute inset-0 flex flex-col items-center justify-center pointer-events-none div class=text-center p-8 bg-white80 darkbg-gray-80080 rounded-xl backdrop-blur-sm border border-gray-200 darkborder-gray-700 shadow-xl i class=fa-solid fa-globe text-6xl text-blue-500 mb-4 opacity-50i h2 class=text-xl font-bold text-gray-700 darktext-gray-300Web Dashboardh2 p class=text-sm text-gray-500 darktext-gray-400 mt-2Select a tool from the toolbar to beginp div div div div !-- SNIPPET OVERLAY -- div id=snippet-overlay class=fixed inset-0 z-[200] bg-black30 hidden div id=selection-box class=hiddendiv div !-- TOAST NOTIFICATION CONTAINER -- div id=toast-container class=fixed top-16 left-12 transform -translate-x-12 z-[300] pointer-events-nonediv script --- THEME LOGIC --- function toggleTheme() { document.documentElement.classList.toggle('dark'); } --- UTILITY LOGIC (TOASTS) --- function showToast(message, isError = false) { const container = document.getElementById('toast-container'); const toast = document.createElement('div'); toast.className = `toast-msg px-4 py-2 rounded-full shadow-lg text-sm font-medium text-white mb-2 ${isError 'bg-red-500' 'bg-green-500'}`; toast.innerHTML = isError `i class=fa-solid fa-triangle-exclamation mr-2i${message}` `i class=fa-solid fa-check mr-2i${message}`; container.appendChild(toast); setTimeout(() = { toast.remove(); }, 3000); } function setActiveTool(btn) { document.querySelectorAll('.tool-btn').forEach(b = b.classList.remove('active')); if(btn) btn.classList.add('active'); } --- SNIPPET TOOL LOGIC --- let isSnipping = false; let startX, startY; const snippetOverlay = document.getElementById('snippet-overlay'); const selectionBox = document.getElementById('selection-box'); function activateSnipMode(btn) { setActiveTool(btn); isSnipping = true; snippetOverlay.classList.remove('hidden'); document.body.style.cursor = 'crosshair'; Reset box selectionBox.classList.add('hidden'); selectionBox.style.width = '0'; selectionBox.style.height = '0'; selectionBox.style.pointerEvents = 'none'; Clean previous image if any selectionBox.innerHTML = ''; selectionBox.style.backgroundColor = 'rgba(59, 130, 246, 0.2)'; } snippetOverlay.addEventListener('mousedown', (e) = { if(selectionBox.contains(e.target) && selectionBox.style.pointerEvents === 'auto') return; isSnipping = true; startX = e.clientX; startY = e.clientY; selectionBox.innerHTML = ''; selectionBox.style.backgroundColor = 'rgba(59, 130, 246, 0.2)'; selectionBox.style.left = startX + 'px'; selectionBox.style.top = startY + 'px'; selectionBox.style.width = '0px'; selectionBox.style.height = '0px'; selectionBox.classList.remove('hidden'); selectionBox.style.pointerEvents = 'none'; }); snippetOverlay.addEventListener('mousemove', (e) = { if(!isSnipping) return; const currentX = e.clientX; const currentY = e.clientY; const width = Math.abs(currentX - startX); const height = Math.abs(currentY - startY); const left = Math.min(currentX, startX); const top = Math.min(currentY, startY); selectionBox.style.width = width + 'px'; selectionBox.style.height = height + 'px'; selectionBox.style.left = left + 'px'; selectionBox.style.top = top + 'px'; }); snippetOverlay.addEventListener('mouseup', async (e) = { if(!isSnipping) return; isSnipping = false; document.body.style.cursor = 'default'; const rect = selectionBox.getBoundingClientRect(); if (rect.width 5 rect.height 5) { selectionBox.classList.add('hidden'); setActiveTool(null); return; } selectionBox.style.pointerEvents = 'auto'; showToast(Processing..., false); try { selectionBox.classList.add('hidden'); const canvas = await html2canvas(document.body, { x rect.left + window.scrollX, y rect.top + window.scrollY, width rect.width, height rect.height, useCORS true, allowTaint true, ignoreElements (element) = element.id === 'snippet-overlay' element.id === 'toast-container' }); selectionBox.classList.remove('hidden'); canvas.toBlob(blob = { if (!blob) { showToast(Failed to capture area., true); setActiveTool(null); return; } const imgUrl = URL.createObjectURL(blob); const img = document.createElement('img'); img.src = imgUrl; img.style.width = '100%'; img.style.height = '100%'; img.style.objectFit = 'fill'; img.style.pointerEvents = 'auto'; selectionBox.innerHTML = ''; selectionBox.appendChild(img); selectionBox.style.backgroundColor = 'transparent'; try { Attempt to focus the window to solve Document is not focused error window.focus(); const item = new ClipboardItem({ 'imagepng' blob }); navigator.clipboard.write([item]).then(() = { showToast(Copied to Clipboard! Right-click selection to Save.); }).catch(err = { console.error(err); showToast(Auto-copy failed. Right-click image to Copy., true); }); } catch (err) { console.error(Clipboard write error, err); showToast(Auto-copy failed. Right-click image to Copy., true); } }); } catch(err) { console.error(Snippet failed, err); showToast(Error capturing screenshot., true); selectionBox.classList.remove('hidden'); setActiveTool(null); } }); --- WEB DASHBOARD LOGIC --- const webFrame = document.getElementById('web-frame'); const urlDisplay = document.getElementById('url-display'); const webPlaceholder = document.getElementById('empty-placeholder'); const btnNewTab = document.getElementById('btn-newtab'); const btnRefresh = document.getElementById('btn-refresh'); function loadWebUrl(url, title, event) { if (event) { const btn = event.currentTarget; if(btn) setActiveTool(btn); if (event.ctrlKey event.metaKey) { window.open(url, '_blank'); return; } } Load in iframe webFrame.src = url; urlDisplay.value = url; webPlaceholder.style.display = 'none'; btnNewTab.classList.remove('hidden'); btnRefresh.classList.remove('hidden'); showToast(`Loading ${title}...`); } --- POPUP WINDOW LOGIC FOR GOOGLECLOUD --- function openPopup(url, title) { Calculate center of screen const width = 1000; const height = 700; const left = (screen.width - width) 2; const top = (screen.height - height) 2; Open window with specific dimensions window.open( url, title, `width=${width},height=${height},top=${top},left=${left},resizable=yes,scrollbars=yes,status=yes` ); showToast(`Opened ${title} in popup window`); } function openCurrentInNewTab() { if(webFrame.src && webFrame.src !== 'aboutblank') { window.open(webFrame.src, '_blank'); } } function refreshWebPage() { if(webFrame.src && webFrame.src !== 'aboutblank') { To force a reload of the iframe const currentUrl = webFrame.src; webFrame.src = currentUrl; showToast(Refreshing page...); } } function clearWebWorkspace() { webFrame.src = 'aboutblank'; urlDisplay.value = ''; webPlaceholder.style.display = 'flex'; btnNewTab.classList.add('hidden'); btnRefresh.classList.add('hidden'); setActiveTool(null); showToast(Workspace Cleared); } Global Escape Key to cancel Snip window.addEventListener('keydown', (e) = { if (e.key === 'Escape') { isSnipping = false; snippetOverlay.classList.add('hidden'); selectionBox.classList.add('hidden'); document.body.style.cursor = 'default'; const screenBtn = document.getElementById('btn-screenshot-web'); if(screenBtn && screenBtn.classList.contains('active')) screenBtn.classList.remove('active'); } }); script body html