2025-11-15 09:48:46 -03:00
|
|
|
<!doctype html>
|
2025-11-15 19:08:26 -03:00
|
|
|
<html lang="en">
|
2025-11-20 14:28:21 -03:00
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8" />
|
|
|
|
|
<title>General Bots</title>
|
|
|
|
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
2025-11-21 07:42:20 -03:00
|
|
|
<meta
|
|
|
|
|
name="description"
|
|
|
|
|
content="General Bots - AI-powered workspace"
|
|
|
|
|
/>
|
|
|
|
|
<meta name="theme-color" content="#3b82f6" />
|
2025-11-20 16:02:48 -03:00
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
<!-- Styles -->
|
|
|
|
|
<link rel="stylesheet" href="css/app.css" />
|
2025-11-30 15:07:29 -03:00
|
|
|
<link rel="stylesheet" href="css/apps-extended.css" />
|
|
|
|
|
<link rel="stylesheet" href="css/components.css" />
|
2025-11-20 16:02:48 -03:00
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
<!-- External Libraries -->
|
2025-11-29 16:29:28 -03:00
|
|
|
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
|
|
|
|
<script src="https://unpkg.com/htmx.org/dist/ext/ws.js"></script>
|
|
|
|
|
<script src="https://unpkg.com/htmx.org/dist/ext/json-enc.js"></script>
|
2025-11-20 14:28:21 -03:00
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
<body>
|
2025-11-20 20:39:20 -03:00
|
|
|
<!-- Loading overlay -->
|
|
|
|
|
<div class="loading-overlay" id="loadingOverlay">
|
|
|
|
|
<div class="loading-spinner"></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
<!-- Floating header -->
|
|
|
|
|
<header class="float-header" role="banner">
|
2025-11-20 16:02:48 -03:00
|
|
|
<!-- Left: General Bots logo -->
|
|
|
|
|
<div class="header-left">
|
2025-11-21 07:42:20 -03:00
|
|
|
<button
|
2025-11-20 20:39:20 -03:00
|
|
|
class="logo-wrapper"
|
|
|
|
|
onclick="window.location.reload()"
|
2025-11-21 07:42:20 -03:00
|
|
|
title="General Bots - Reload"
|
|
|
|
|
aria-label="General Bots - Reload application"
|
2025-11-20 20:39:20 -03:00
|
|
|
>
|
2025-11-21 07:42:20 -03:00
|
|
|
<div
|
|
|
|
|
class="logo-icon"
|
|
|
|
|
role="img"
|
|
|
|
|
aria-label="General Bots logo"
|
|
|
|
|
></div>
|
2025-11-20 20:39:20 -03:00
|
|
|
<span class="logo-text">General Bots</span>
|
2025-11-21 07:42:20 -03:00
|
|
|
</button>
|
2025-11-20 16:02:48 -03:00
|
|
|
</div>
|
|
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
<!-- Right: Theme selector, Apps menu and user avatar -->
|
2025-11-20 16:02:48 -03:00
|
|
|
<div class="header-right">
|
2025-11-20 20:39:20 -03:00
|
|
|
<!-- Theme dropdown selector -->
|
2025-11-21 07:42:20 -03:00
|
|
|
<div
|
|
|
|
|
id="themeSelectorContainer"
|
|
|
|
|
aria-label="Theme selector"
|
|
|
|
|
></div>
|
2025-11-20 20:39:20 -03:00
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
<!-- Apps menu button -->
|
2025-11-20 20:39:20 -03:00
|
|
|
<button
|
|
|
|
|
class="icon-button apps-button"
|
|
|
|
|
id="appsButton"
|
2025-11-21 07:42:20 -03:00
|
|
|
title="Applications"
|
|
|
|
|
aria-label="Open applications menu"
|
|
|
|
|
aria-expanded="false"
|
|
|
|
|
aria-haspopup="true"
|
2025-11-20 20:39:20 -03:00
|
|
|
>
|
2025-11-20 16:02:48 -03:00
|
|
|
<svg
|
|
|
|
|
width="24"
|
|
|
|
|
height="24"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="currentColor"
|
2025-11-21 07:42:20 -03:00
|
|
|
aria-hidden="true"
|
2025-11-20 16:02:48 -03:00
|
|
|
>
|
|
|
|
|
<circle cx="5" cy="5" r="2"></circle>
|
|
|
|
|
<circle cx="12" cy="5" r="2"></circle>
|
|
|
|
|
<circle cx="19" cy="5" r="2"></circle>
|
|
|
|
|
<circle cx="5" cy="12" r="2"></circle>
|
|
|
|
|
<circle cx="12" cy="12" r="2"></circle>
|
|
|
|
|
<circle cx="19" cy="12" r="2"></circle>
|
|
|
|
|
<circle cx="5" cy="19" r="2"></circle>
|
|
|
|
|
<circle cx="12" cy="19" r="2"></circle>
|
|
|
|
|
<circle cx="19" cy="19" r="2"></circle>
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
2025-11-21 07:42:20 -03:00
|
|
|
|
|
|
|
|
<!-- Apps dropdown menu -->
|
|
|
|
|
<nav
|
|
|
|
|
class="apps-dropdown"
|
|
|
|
|
id="appsDropdown"
|
|
|
|
|
role="menu"
|
|
|
|
|
aria-label="Applications"
|
|
|
|
|
>
|
2025-11-20 20:39:20 -03:00
|
|
|
<div class="apps-dropdown-title">Applications</div>
|
2025-11-21 07:42:20 -03:00
|
|
|
<div class="app-grid" role="group">
|
2025-11-30 15:07:29 -03:00
|
|
|
<!-- Chat -->
|
2025-11-20 16:02:48 -03:00
|
|
|
<a
|
|
|
|
|
class="app-item active"
|
|
|
|
|
href="#chat"
|
|
|
|
|
data-section="chat"
|
2025-11-21 07:42:20 -03:00
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Chat application"
|
2025-11-29 16:29:28 -03:00
|
|
|
hx-get="/api/chat"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
2025-11-20 16:02:48 -03:00
|
|
|
>
|
2025-11-30 15:07:29 -03:00
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<path
|
|
|
|
|
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
|
|
|
|
/>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
2025-11-20 16:02:48 -03:00
|
|
|
<span>Chat</span>
|
|
|
|
|
</a>
|
2025-11-30 15:07:29 -03:00
|
|
|
|
|
|
|
|
<!-- Research</span> -->
|
|
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#research"
|
|
|
|
|
data-section="research"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Research application"
|
|
|
|
|
hx-get="research/research.html"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
|
|
|
|
>
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<circle cx="11" cy="11" r="8" />
|
|
|
|
|
<path d="m21 21-4.35-4.35" />
|
|
|
|
|
<path d="M11 8v6M8 11h6" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<span>Research</span>
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<!-- Paper -->
|
|
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#paper"
|
|
|
|
|
data-section="paper"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Paper - Notes & Writing"
|
|
|
|
|
hx-get="paper/paper.html"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
|
|
|
|
>
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<path
|
|
|
|
|
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
|
|
|
|
/>
|
|
|
|
|
<polyline points="14 2 14 8 20 8" />
|
|
|
|
|
<line x1="16" y1="13" x2="8" y2="13" />
|
|
|
|
|
<line x1="16" y1="17" x2="8" y2="17" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<span>Paper</span>
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<!-- Drive -->
|
2025-11-21 07:42:20 -03:00
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#drive"
|
|
|
|
|
data-section="drive"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Drive application"
|
2025-11-29 16:29:28 -03:00
|
|
|
hx-get="/api/drive/list"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
2025-11-21 07:42:20 -03:00
|
|
|
>
|
2025-11-30 15:07:29 -03:00
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<path
|
|
|
|
|
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
|
|
|
|
|
/>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
2025-11-20 16:02:48 -03:00
|
|
|
<span>Drive</span>
|
|
|
|
|
</a>
|
2025-11-30 15:07:29 -03:00
|
|
|
|
|
|
|
|
<!-- Calendar -->
|
|
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#calendar"
|
|
|
|
|
data-section="calendar"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Calendar application"
|
|
|
|
|
hx-get="calendar/calendar.html"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
|
|
|
|
>
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<rect
|
|
|
|
|
x="3"
|
|
|
|
|
y="4"
|
|
|
|
|
width="18"
|
|
|
|
|
height="18"
|
|
|
|
|
rx="2"
|
|
|
|
|
ry="2"
|
|
|
|
|
/>
|
|
|
|
|
<line x1="16" y1="2" x2="16" y2="6" />
|
|
|
|
|
<line x1="8" y1="2" x2="8" y2="6" />
|
|
|
|
|
<line x1="3" y1="10" x2="21" y2="10" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<span>Calendar</span>
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<!-- Tasks -->
|
2025-11-21 07:42:20 -03:00
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#tasks"
|
|
|
|
|
data-section="tasks"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Tasks application"
|
2025-11-29 16:29:28 -03:00
|
|
|
hx-get="/api/tasks"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
2025-11-21 07:42:20 -03:00
|
|
|
>
|
2025-11-30 15:07:29 -03:00
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<path d="M9 11l3 3L22 4" />
|
|
|
|
|
<path
|
|
|
|
|
d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"
|
|
|
|
|
/>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
2025-11-20 16:02:48 -03:00
|
|
|
<span>Tasks</span>
|
|
|
|
|
</a>
|
2025-11-30 15:07:29 -03:00
|
|
|
|
|
|
|
|
<!-- Mail -->
|
2025-11-21 07:42:20 -03:00
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#mail"
|
|
|
|
|
data-section="mail"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Mail application"
|
2025-11-29 16:29:28 -03:00
|
|
|
hx-get="/api/email/latest"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
2025-11-21 07:42:20 -03:00
|
|
|
>
|
2025-11-30 15:07:29 -03:00
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<path
|
|
|
|
|
d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"
|
|
|
|
|
/>
|
|
|
|
|
<polyline points="22,6 12,13 2,6" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
2025-11-20 16:02:48 -03:00
|
|
|
<span>Mail</span>
|
|
|
|
|
</a>
|
2025-11-30 15:07:29 -03:00
|
|
|
|
|
|
|
|
<!-- Meet -->
|
|
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#meet"
|
|
|
|
|
data-section="meet"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Meet application"
|
|
|
|
|
hx-get="meet/meet.html"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
|
|
|
|
>
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<polygon points="23 7 16 12 23 17 23 7" />
|
|
|
|
|
<rect
|
|
|
|
|
x="1"
|
|
|
|
|
y="5"
|
|
|
|
|
width="15"
|
|
|
|
|
height="14"
|
|
|
|
|
rx="2"
|
|
|
|
|
ry="2"
|
|
|
|
|
/>
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<span>Meet</span>
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<!-- Analytics -->
|
|
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#analytics"
|
|
|
|
|
data-section="analytics"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="Analytics Dashboard"
|
|
|
|
|
hx-get="analytics/analytics.html"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
|
|
|
|
>
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<line x1="18" y1="20" x2="18" y2="10" />
|
|
|
|
|
<line x1="12" y1="20" x2="12" y2="4" />
|
|
|
|
|
<line x1="6" y1="20" x2="6" y2="14" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<span>Analytics</span>
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
<!-- Monitoring -->
|
|
|
|
|
<a
|
|
|
|
|
class="app-item"
|
|
|
|
|
href="#monitoring"
|
|
|
|
|
data-section="monitoring"
|
|
|
|
|
role="menuitem"
|
|
|
|
|
aria-label="System Monitoring"
|
|
|
|
|
hx-get="monitoring/monitoring.html"
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
hx-push-url="true"
|
|
|
|
|
>
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
<svg
|
|
|
|
|
width="20"
|
|
|
|
|
height="20"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
>
|
|
|
|
|
<circle cx="12" cy="12" r="10" />
|
|
|
|
|
<circle cx="12" cy="12" r="6" />
|
|
|
|
|
<circle cx="12" cy="12" r="2" />
|
|
|
|
|
</svg>
|
|
|
|
|
</div>
|
|
|
|
|
<span>Monitoring</span>
|
|
|
|
|
</a>
|
2025-11-20 16:02:48 -03:00
|
|
|
</div>
|
2025-11-21 07:42:20 -03:00
|
|
|
</nav>
|
2025-11-20 20:39:20 -03:00
|
|
|
|
|
|
|
|
<!-- User avatar -->
|
2025-11-21 07:42:20 -03:00
|
|
|
<button
|
|
|
|
|
class="user-avatar"
|
|
|
|
|
id="userAvatar"
|
|
|
|
|
title="User Account"
|
|
|
|
|
aria-label="User account menu"
|
|
|
|
|
>
|
|
|
|
|
<span aria-hidden="true">U</span>
|
|
|
|
|
</button>
|
2025-11-20 16:02:48 -03:00
|
|
|
</div>
|
2025-11-21 07:42:20 -03:00
|
|
|
</header>
|
2025-11-20 14:28:21 -03:00
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
<!-- Main content area -->
|
2025-11-29 16:29:28 -03:00
|
|
|
<main
|
|
|
|
|
id="main-content"
|
|
|
|
|
role="main"
|
|
|
|
|
hx-ext="ws"
|
|
|
|
|
ws-connect="/ws/notifications"
|
|
|
|
|
>
|
2025-11-20 14:28:21 -03:00
|
|
|
<!-- Sections will be loaded dynamically -->
|
2025-11-21 07:42:20 -03:00
|
|
|
</main>
|
2025-11-20 14:28:21 -03:00
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
<!-- Core scripts -->
|
2025-11-20 20:39:20 -03:00
|
|
|
<script src="js/theme-manager.js"></script>
|
2025-11-29 16:29:28 -03:00
|
|
|
<script src="js/htmx-app.js"></script>
|
2025-11-21 07:42:20 -03:00
|
|
|
|
|
|
|
|
<!-- Application initialization -->
|
2025-11-20 14:40:15 -03:00
|
|
|
<script>
|
2025-11-29 16:29:28 -03:00
|
|
|
// Simple initialization for HTMX app
|
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
|
|
|
console.log("🚀 Initializing General Bots with HTMX...");
|
|
|
|
|
|
|
|
|
|
// Hide loading overlay
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
const loadingOverlay =
|
|
|
|
|
document.getElementById("loadingOverlay");
|
|
|
|
|
if (loadingOverlay) {
|
|
|
|
|
loadingOverlay.classList.add("hidden");
|
2025-11-21 07:42:20 -03:00
|
|
|
}
|
2025-11-29 16:29:28 -03:00
|
|
|
}, 500);
|
2025-11-20 16:02:48 -03:00
|
|
|
|
2025-11-29 16:29:28 -03:00
|
|
|
// Simple apps menu handling
|
|
|
|
|
const appsBtn = document.getElementById("appsButton");
|
|
|
|
|
const appsDropdown = document.getElementById("appsDropdown");
|
2025-11-20 16:02:48 -03:00
|
|
|
|
2025-11-29 16:29:28 -03:00
|
|
|
if (appsBtn && appsDropdown) {
|
2025-11-21 07:42:20 -03:00
|
|
|
appsBtn.addEventListener("click", (e) => {
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
const isOpen = appsDropdown.classList.toggle("show");
|
|
|
|
|
appsBtn.setAttribute("aria-expanded", isOpen);
|
|
|
|
|
});
|
2025-11-20 14:40:15 -03:00
|
|
|
|
2025-11-21 07:42:20 -03:00
|
|
|
document.addEventListener("click", (e) => {
|
|
|
|
|
if (
|
|
|
|
|
!appsDropdown.contains(e.target) &&
|
|
|
|
|
!appsBtn.contains(e.target)
|
|
|
|
|
) {
|
|
|
|
|
appsDropdown.classList.remove("show");
|
|
|
|
|
appsBtn.setAttribute("aria-expanded", "false");
|
2025-11-20 16:02:48 -03:00
|
|
|
}
|
2025-11-21 07:42:20 -03:00
|
|
|
});
|
|
|
|
|
}
|
2025-11-30 15:07:29 -03:00
|
|
|
|
|
|
|
|
// Handle app item clicks - update active state
|
|
|
|
|
document.querySelectorAll(".app-item").forEach((item) => {
|
|
|
|
|
item.addEventListener("click", function () {
|
|
|
|
|
document
|
|
|
|
|
.querySelectorAll(".app-item")
|
|
|
|
|
.forEach((i) => i.classList.remove("active"));
|
|
|
|
|
this.classList.add("active");
|
|
|
|
|
appsDropdown.classList.remove("show");
|
|
|
|
|
appsBtn.setAttribute("aria-expanded", "false");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Handle hash navigation
|
|
|
|
|
function handleHashChange() {
|
|
|
|
|
const hash = window.location.hash.slice(1) || "chat";
|
|
|
|
|
const appItem = document.querySelector(
|
|
|
|
|
`[data-section="${hash}"]`,
|
|
|
|
|
);
|
|
|
|
|
if (appItem) {
|
|
|
|
|
document
|
|
|
|
|
.querySelectorAll(".app-item")
|
|
|
|
|
.forEach((i) => i.classList.remove("active"));
|
|
|
|
|
appItem.classList.add("active");
|
|
|
|
|
|
|
|
|
|
// Trigger HTMX load if not already loaded
|
|
|
|
|
const hxGet = appItem.getAttribute("hx-get");
|
|
|
|
|
if (hxGet) {
|
|
|
|
|
htmx.ajax("GET", hxGet, {
|
|
|
|
|
target: "#main-content",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load initial content based on hash or default to chat
|
|
|
|
|
window.addEventListener("hashchange", handleHashChange);
|
|
|
|
|
|
|
|
|
|
// Initial load
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
handleHashChange();
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
|
|
// Keyboard shortcuts
|
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
|
|
|
// Alt + number for quick app switching
|
|
|
|
|
if (e.altKey && !e.ctrlKey && !e.shiftKey) {
|
|
|
|
|
const num = parseInt(e.key);
|
|
|
|
|
if (num >= 1 && num <= 9) {
|
|
|
|
|
const items =
|
|
|
|
|
document.querySelectorAll(".app-item");
|
|
|
|
|
if (items[num - 1]) {
|
|
|
|
|
items[num - 1].click();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Alt + A to open apps menu
|
|
|
|
|
if (e.altKey && e.key.toLowerCase() === "a") {
|
|
|
|
|
appsBtn.click();
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
});
|
2025-11-29 16:29:28 -03:00
|
|
|
});
|
2025-11-20 14:40:15 -03:00
|
|
|
</script>
|
2025-11-20 14:28:21 -03:00
|
|
|
</body>
|
|
|
|
|
</html>
|