!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