Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ services:
condition: service_healthy
required: false
volumes:
- ./finbot:/app/finbot
- sqlite_data:/app/data
- uploads:/app/uploads
- cache:/app/cache
Expand Down
42 changes: 39 additions & 3 deletions finbot/apps/admin/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@
<body class="bg-portal-bg-primary flex flex-col min-h-screen">
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 px-4 py-2 rounded-md z-50 font-medium">Skip to main content</a>

<div class="flex flex-1 min-h-0 relative z-10 overflow-hidden bg-portal-bg-primary">
<div class="flex flex-1 min-h-0 bg-portal-bg-primary">
<!-- Sidebar -->
<aside id="sidebar" class="ai-sidebar w-80 flex-shrink-0 flex flex-col overflow-y-auto border-r border-admin-primary/20 bg-portal-bg-secondary/50">
<aside id="sidebar" class="ai-sidebar w-80 flex-shrink-0 flex flex-col sticky top-0 h-screen overflow-y-auto border-r border-admin-primary/20 bg-portal-bg-secondary/50">
<!-- Logo -->
<div class="sidebar-logo-section p-6 border-b border-admin-primary/20">
<div class="flex items-center space-x-3">
Expand Down Expand Up @@ -259,11 +259,47 @@ <h1 class="text-2xl font-bold text-text-bright">{% block page_title %}Dashboard{
<script src="{{ url_for('static', path='js/common/utils.js') }}"></script>
<script src="{{ url_for('static', path='js/common/api.js') }}"></script>
<script>
// Initialize mobile sidebar on all pages
// Initialize mobile sidebar + inline touch navigation (bypasses caching)
function _attachMobileSidebarNav() {
var sidebar = document.getElementById('sidebar');
if (!sidebar) return;
var links = sidebar.querySelectorAll('a[href]');
links.forEach(function(link) {
// touchend fires after finger lifts - direct nav, no CSS blocking
link.addEventListener('touchend', function(e) {
var href = link.getAttribute('href');
if (href && href !== '#' && href !== '') {
e.stopImmediatePropagation();
e.preventDefault();
window.location.href = href;
}
}, true);
// Also handle click as fallback
link.addEventListener('click', function(e) {
var href = link.getAttribute('href');
if (href && href !== '#' && href !== '') {
window.location.href = href;
}
}, true);
});
}

document.addEventListener('DOMContentLoaded', function() {
if (typeof sidebar !== 'undefined' && sidebar.init) {
sidebar.init('#sidebar');
}
// Attach touch nav immediately
_attachMobileSidebarNav();
// Also attach when sidebar opens (in case it's re-rendered)
var hamburger = document.querySelector('.sidebar-toggle');
if (hamburger) {
hamburger.addEventListener('touchend', function() {
setTimeout(_attachMobileSidebarNav, 100);
}, true);
hamburger.addEventListener('click', function() {
setTimeout(_attachMobileSidebarNav, 100);
}, true);
}
});
</script>
{% block extra_js %}{% endblock %}
Expand Down
37 changes: 35 additions & 2 deletions finbot/apps/darklab/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@
<body class="bg-portal-bg-primary flex flex-col min-h-screen">
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 px-4 py-2 rounded-md z-50 font-medium">Skip to main content</a>

<div class="flex flex-1 min-h-0 relative z-10 overflow-hidden bg-portal-bg-primary">
<div class="flex flex-1 min-h-0 bg-portal-bg-primary">
<!-- Sidebar -->
<aside id="sidebar" class="ai-sidebar w-80 flex-shrink-0 flex flex-col overflow-y-auto border-r border-darklab-primary/20 bg-portal-bg-secondary/50">
<aside id="sidebar" class="ai-sidebar w-80 flex-shrink-0 flex flex-col sticky top-0 h-screen overflow-y-auto border-r border-darklab-primary/20 bg-portal-bg-secondary/50">
<!-- Logo -->
<div class="sidebar-logo-section p-6 border-b border-darklab-primary/20">
<div class="flex items-center space-x-3">
Expand Down Expand Up @@ -238,10 +238,43 @@ <h1 class="text-2xl font-bold text-text-bright">{% block page_title %}Dashboard{
<script src="{{ url_for('static', path='js/common/utils.js') }}"></script>
<script src="{{ url_for('static', path='js/common/api.js') }}"></script>
<script>
// Initialize mobile sidebar + inline touch navigation (bypasses caching)
function _attachMobileSidebarNav() {
var sidebar = document.getElementById('sidebar');
if (!sidebar) return;
var links = sidebar.querySelectorAll('a[href]');
links.forEach(function(link) {
link.addEventListener('touchend', function(e) {
var href = link.getAttribute('href');
if (href && href !== '#' && href !== '') {
e.stopImmediatePropagation();
e.preventDefault();
window.location.href = href;
}
}, true);
link.addEventListener('click', function(e) {
var href = link.getAttribute('href');
if (href && href !== '#' && href !== '') {
window.location.href = href;
}
}, true);
});
}

document.addEventListener('DOMContentLoaded', function() {
if (typeof sidebar !== 'undefined' && sidebar.init) {
sidebar.init('#sidebar');
}
_attachMobileSidebarNav();
var hamburger = document.querySelector('.sidebar-toggle');
if (hamburger) {
hamburger.addEventListener('touchend', function() {
setTimeout(_attachMobileSidebarNav, 100);
}, true);
hamburger.addEventListener('click', function() {
setTimeout(_attachMobileSidebarNav, 100);
}, true);
}
});
</script>
{% block extra_js %}{% endblock %}
Expand Down
20 changes: 14 additions & 6 deletions finbot/static/css/vendor/portal.css
Original file line number Diff line number Diff line change
Expand Up @@ -1333,7 +1333,7 @@ body {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 1002;
z-index: 10002;
background: rgba(21, 21, 32, 0.95);
border: 2px solid rgba(255, 255, 255, 0.2);
border-radius: 6px;
Expand Down Expand Up @@ -1375,7 +1375,7 @@ body {
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 999;
z-index: 10000;
opacity: 0;
visibility: hidden;
pointer-events: none;
Expand All @@ -1397,7 +1397,7 @@ body {
width: 320px;
transform: translateX(-100%);
transition: transform 0.3s ease;
z-index: 1001;
z-index: 10001;
box-shadow: 2px 0 20px rgba(0, 0, 0, 0.5);
background: #0a0a0f !important;
backdrop-filter: none !important;
Expand All @@ -1410,11 +1410,19 @@ body {
/* Show sidebar when open */
.ai-sidebar.open {
transform: translateX(0);
pointer-events: auto;
pointer-events: auto !important;
}

.ai-sidebar * {
pointer-events: auto;
.ai-sidebar.open * {
pointer-events: auto !important;
}

.ai-sidebar.open a,
.ai-sidebar.open button {
pointer-events: auto !important;
cursor: pointer !important;
position: relative !important;
z-index: 10003 !important;
}

/* Adjust main content */
Expand Down
18 changes: 18 additions & 0 deletions finbot/static/js/common/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,24 @@ const sidebar = {
if (this.state.toggleButton) {
this.state.toggleButton.classList.add('hidden');
}

// Mobile touch navigation: attach touchend handlers to all sidebar links
// This bypasses CSS stacking/pointer-events issues on mobile
if ('ontouchstart' in window) {
const links = sidebarElement.querySelectorAll('a[href]');
links.forEach(link => {
if (!link._touchNavBound) {
link._touchNavBound = true;
link.addEventListener('touchend', function(e) {
e.stopPropagation();
const href = this.getAttribute('href');
if (href && href !== '#') {
window.location.href = href;
}
}, { passive: false });
}
});
}
},

close(sidebarSelector) {
Expand Down