Add sidenav layout for authenticated dashboard
- Create dashboard_base.html: standalone app shell with 56px sticky header (logo + user email + sign out), 220px left sidebar with Overview/Countries/Settings nav items (SVG icons, active state via request.path), and fixed mobile bottom tab bar (md:hidden) - Add CSS component classes: .app-shell, .app-header, .app-sidebar, .sidebar-item, .app-content, .mobile-bottom-nav, .mobile-nav-item - Extract feedback widget into _feedback_widget.html partial; include from both base.html and dashboard_base.html - Switch index.html, countries.html, settings.html to extend dashboard_base.html; remove <main class="container-page"> wrappers - Remove "Back to Dashboard" button from countries.html (sidebar provides persistent navigation) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
{% extends "base.html" %}
|
||||
{% extends "dashboard_base.html" %}
|
||||
|
||||
{% block title %}Country Comparison — {{ config.APP_NAME }}{% endblock %}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="container-page py-8">
|
||||
<!-- Page Header -->
|
||||
<div class="page-header">
|
||||
<h1>Country Comparison</h1>
|
||||
@@ -51,8 +50,6 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<a href="{{ url_for('dashboard.index') }}" class="btn-outline">Back to Dashboard</a>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
130
web/src/beanflows/dashboard/templates/dashboard_base.html
Normal file
130
web/src/beanflows/dashboard/templates/dashboard_base.html
Normal file
@@ -0,0 +1,130 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}{{ config.APP_NAME }}{% endblock %}</title>
|
||||
<link rel="icon" href="{{ url_for('static', filename='favicon.svg') }}" type="image/svg+xml">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Fraunces:ital,opsz,wght@0,9..144,100..900;1,9..144,100..900&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/output.css') }}">
|
||||
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body class="bg-cream">
|
||||
|
||||
<!-- ── App Shell ── -->
|
||||
<div class="app-shell">
|
||||
|
||||
<!-- Slim App Header -->
|
||||
<header class="app-header">
|
||||
<a href="{{ url_for('public.landing') }}" class="nav-logo">{{ config.APP_NAME }}</a>
|
||||
<div class="app-header-right">
|
||||
{% if session.get('is_admin') %}
|
||||
<a href="{{ url_for('admin.index') }}" class="nav-badge hidden sm:inline">Admin</a>
|
||||
{% endif %}
|
||||
<span class="app-header-email">{{ user.email }}</span>
|
||||
<form method="post" action="{{ url_for('auth.logout') }}" class="nav-form">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<button type="submit" class="btn-outline btn-sm">Sign Out</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Body: sidebar + content -->
|
||||
<div class="app-body">
|
||||
|
||||
<!-- ── Sidebar (desktop) ── -->
|
||||
<nav class="app-sidebar" aria-label="Main navigation">
|
||||
<a href="{{ url_for('dashboard.index') }}"
|
||||
class="sidebar-item{% if request.path == '/dashboard/' %} active{% endif %}">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<rect x="3" y="3" width="7" height="7" rx="1.5"/>
|
||||
<rect x="14" y="3" width="7" height="7" rx="1.5"/>
|
||||
<rect x="3" y="14" width="7" height="7" rx="1.5"/>
|
||||
<rect x="14" y="14" width="7" height="7" rx="1.5"/>
|
||||
</svg>
|
||||
Overview
|
||||
</a>
|
||||
<a href="{{ url_for('dashboard.countries') }}"
|
||||
class="sidebar-item{% if request.path.startswith('/dashboard/countries') %} active{% endif %}">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="9"/>
|
||||
<path d="M3 12h18"/>
|
||||
<path d="M12 3c-3.5 4.5-3.5 13.5 0 18"/>
|
||||
<path d="M12 3c3.5 4.5 3.5 13.5 0 18"/>
|
||||
</svg>
|
||||
Countries
|
||||
</a>
|
||||
<a href="{{ url_for('dashboard.settings') }}"
|
||||
class="sidebar-item{% if request.path.startswith('/dashboard/settings') %} active{% endif %}">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
<path d="M12 2v2M12 20v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M2 12h2M20 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
||||
</svg>
|
||||
Settings
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- ── Main Content ── -->
|
||||
<main class="app-content">
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="{% if category == 'error' %}flash-error{% elif category == 'success' %}flash-success{% elif category == 'warning' %}flash-warning{% else %}flash{% endif %} mb-4">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Mobile Bottom Nav ── -->
|
||||
<nav class="mobile-bottom-nav" aria-label="Mobile navigation">
|
||||
<a href="{{ url_for('dashboard.index') }}"
|
||||
class="mobile-nav-item{% if request.path == '/dashboard/' %} active{% endif %}">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24">
|
||||
<rect x="3" y="3" width="7" height="7" rx="1.5"/>
|
||||
<rect x="14" y="3" width="7" height="7" rx="1.5"/>
|
||||
<rect x="3" y="14" width="7" height="7" rx="1.5"/>
|
||||
<rect x="14" y="14" width="7" height="7" rx="1.5"/>
|
||||
</svg>
|
||||
<span>Overview</span>
|
||||
</a>
|
||||
<a href="{{ url_for('dashboard.countries') }}"
|
||||
class="mobile-nav-item{% if request.path.startswith('/dashboard/countries') %} active{% endif %}">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" viewBox="0 0 24 24">
|
||||
<circle cx="12" cy="12" r="9"/>
|
||||
<path d="M3 12h18"/>
|
||||
<path d="M12 3c-3.5 4.5-3.5 13.5 0 18"/>
|
||||
<path d="M12 3c3.5 4.5 3.5 13.5 0 18"/>
|
||||
</svg>
|
||||
<span>Countries</span>
|
||||
</a>
|
||||
<a href="{{ url_for('dashboard.settings') }}"
|
||||
class="mobile-nav-item{% if request.path.startswith('/dashboard/settings') %} active{% endif %}">
|
||||
<svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" viewBox="0 0 24 24">
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
<path d="M12 2v2M12 20v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M2 12h2M20 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
||||
</svg>
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- HTMX -->
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
|
||||
{% include "_feedback_widget.html" %}
|
||||
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
{% extends "base.html" %}
|
||||
{% extends "dashboard_base.html" %}
|
||||
|
||||
{% block title %}Dashboard — {{ config.APP_NAME }}{% endblock %}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="container-page py-8">
|
||||
<!-- Page Header -->
|
||||
<div class="page-header">
|
||||
<h1>Coffee Dashboard</h1>
|
||||
@@ -154,7 +153,6 @@
|
||||
<a href="{{ url_for('dashboard.settings') }}" class="btn-outline text-center">Settings</a>
|
||||
<a href="{{ url_for('dashboard.settings') }}#api-keys" class="btn-outline text-center">API Keys</a>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
{% extends "base.html" %}
|
||||
{% extends "dashboard_base.html" %}
|
||||
|
||||
{% block title %}Settings — {{ config.APP_NAME }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<main class="container-page py-8">
|
||||
<!-- Page Header -->
|
||||
<div class="page-header">
|
||||
<h1>Settings</h1>
|
||||
@@ -153,5 +152,4 @@
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
@@ -153,6 +153,136 @@
|
||||
@apply max-w-6xl mx-auto px-4 sm:px-6 lg:px-8;
|
||||
}
|
||||
|
||||
/* ── App Shell (authenticated dashboard layout) ── */
|
||||
.app-shell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.app-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 50;
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 1.5rem;
|
||||
background: rgba(255, 251, 245, 0.92);
|
||||
backdrop-filter: blur(14px);
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
border-bottom: 1px solid rgba(232, 223, 213, 0.7);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.app-header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
.app-header-email {
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-stone);
|
||||
display: none;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 200px;
|
||||
}
|
||||
@media (min-width: 640px) {
|
||||
.app-header-email { display: block; }
|
||||
}
|
||||
.app-body {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
.app-sidebar {
|
||||
width: 220px;
|
||||
flex-shrink: 0;
|
||||
padding: 1.25rem 0.75rem;
|
||||
border-right: 1px solid var(--color-parchment);
|
||||
position: sticky;
|
||||
top: 56px;
|
||||
height: calc(100vh - 56px);
|
||||
overflow-y: auto;
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.app-sidebar { display: block; }
|
||||
}
|
||||
.sidebar-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.625rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: 0.625rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-stone-dark);
|
||||
text-decoration: none;
|
||||
transition: background 0.12s, color 0.12s;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.sidebar-item:hover {
|
||||
background: var(--color-latte);
|
||||
color: var(--color-espresso);
|
||||
}
|
||||
.sidebar-item.active {
|
||||
background: rgba(180, 83, 9, 0.08);
|
||||
color: var(--color-copper);
|
||||
font-weight: 600;
|
||||
}
|
||||
.sidebar-item.active svg {
|
||||
stroke: var(--color-copper);
|
||||
}
|
||||
.app-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 2rem 2rem 5rem;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.app-content { padding: 2rem 2.5rem 2rem; }
|
||||
}
|
||||
|
||||
/* ── Mobile bottom navigation ── */
|
||||
.mobile-bottom-nav {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
background: rgba(255, 251, 245, 0.97);
|
||||
backdrop-filter: blur(14px);
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
border-top: 1px solid rgba(232, 223, 213, 0.7);
|
||||
z-index: 50;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.mobile-bottom-nav { display: none; }
|
||||
}
|
||||
.mobile-nav-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 3px;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-stone);
|
||||
text-decoration: none;
|
||||
transition: color 0.12s;
|
||||
}
|
||||
.mobile-nav-item:hover,
|
||||
.mobile-nav-item.active {
|
||||
color: var(--color-copper);
|
||||
}
|
||||
.mobile-nav-item.active svg {
|
||||
stroke: var(--color-copper);
|
||||
}
|
||||
|
||||
/* ── Display headings (Fraunces serif) ── */
|
||||
.heading-display {
|
||||
font-family: var(--font-display);
|
||||
|
||||
86
web/src/beanflows/templates/_feedback_widget.html
Normal file
86
web/src/beanflows/templates/_feedback_widget.html
Normal file
@@ -0,0 +1,86 @@
|
||||
<!-- Feedback Widget -->
|
||||
<div id="feedback-widget" style="position:fixed;bottom:20px;right:20px;z-index:100;">
|
||||
<button
|
||||
id="feedback-btn"
|
||||
onclick="document.getElementById('feedback-popover').classList.toggle('open')"
|
||||
style="
|
||||
background:#2C1810;color:#fff;border:none;border-radius:20px;
|
||||
padding:8px 16px;font-size:13px;font-weight:600;cursor:pointer;
|
||||
box-shadow:0 4px 12px rgba(0,0,0,0.2);display:flex;align-items:center;gap:6px;
|
||||
transition:background 0.15s;
|
||||
"
|
||||
onmouseover="this.style.background='#4A2C1A'"
|
||||
onmouseout="this.style.background='#2C1810'"
|
||||
>
|
||||
<svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<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>
|
||||
Feedback
|
||||
</button>
|
||||
|
||||
<div
|
||||
id="feedback-popover"
|
||||
style="
|
||||
display:none;position:absolute;bottom:44px;right:0;
|
||||
width:300px;background:#fff;border:1px solid #E8DFD5;
|
||||
border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,0.12);
|
||||
padding:16px;
|
||||
"
|
||||
>
|
||||
<p style="font-size:14px;font-weight:600;color:#2C1810;margin:0 0 4px;">Share feedback</p>
|
||||
<p style="font-size:12px;color:#78716C;margin:0 0 12px;">What's on your mind?</p>
|
||||
<form
|
||||
hx-post="{{ url_for('public.feedback') }}"
|
||||
hx-target="#feedback-result"
|
||||
hx-swap="innerHTML"
|
||||
hx-on::after-request="this.reset()"
|
||||
>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<input type="hidden" name="page_url" id="feedback-page-url" value="">
|
||||
<textarea
|
||||
name="message"
|
||||
placeholder="Tell us what you think..."
|
||||
required
|
||||
maxlength="2000"
|
||||
style="
|
||||
width:100%;box-sizing:border-box;resize:vertical;min-height:80px;
|
||||
border:1px solid #E8DFD5;border-radius:6px;padding:8px 10px;
|
||||
font-size:13px;color:#2C1810;outline:none;font-family:inherit;
|
||||
transition:border-color 0.15s;
|
||||
"
|
||||
onfocus="this.style.borderColor='#B45309'"
|
||||
onblur="this.style.borderColor='#E8DFD5'"
|
||||
></textarea>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;">
|
||||
<div id="feedback-result" style="font-size:12px;"></div>
|
||||
<button
|
||||
type="submit"
|
||||
style="
|
||||
background:#B45309;color:#fff;border:none;border-radius:6px;
|
||||
padding:6px 14px;font-size:13px;font-weight:600;cursor:pointer;
|
||||
transition:background 0.15s;flex-shrink:0;
|
||||
"
|
||||
onmouseover="this.style.background='#92400E'"
|
||||
onmouseout="this.style.background='#B45309'"
|
||||
>Send</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#feedback-popover.open { display: block; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var urlInput = document.getElementById('feedback-page-url');
|
||||
if (urlInput) urlInput.value = window.location.href;
|
||||
|
||||
document.addEventListener('click', function(e) {
|
||||
var widget = document.getElementById('feedback-widget');
|
||||
if (widget && !widget.contains(e.target)) {
|
||||
var popover = document.getElementById('feedback-popover');
|
||||
if (popover) popover.classList.remove('open');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -96,92 +96,7 @@
|
||||
<!-- HTMX -->
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
|
||||
<!-- Feedback Widget -->
|
||||
<div id="feedback-widget" style="position:fixed;bottom:20px;right:20px;z-index:100;">
|
||||
<button
|
||||
id="feedback-btn"
|
||||
onclick="document.getElementById('feedback-popover').classList.toggle('open')"
|
||||
style="
|
||||
background:#2C1810;color:#fff;border:none;border-radius:20px;
|
||||
padding:8px 16px;font-size:13px;font-weight:600;cursor:pointer;
|
||||
box-shadow:0 4px 12px rgba(0,0,0,0.2);display:flex;align-items:center;gap:6px;
|
||||
transition:background 0.15s;
|
||||
"
|
||||
onmouseover="this.style.background='#4A2C1A'"
|
||||
onmouseout="this.style.background='#2C1810'"
|
||||
>
|
||||
<svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<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>
|
||||
Feedback
|
||||
</button>
|
||||
|
||||
<div
|
||||
id="feedback-popover"
|
||||
style="
|
||||
display:none;position:absolute;bottom:44px;right:0;
|
||||
width:300px;background:#fff;border:1px solid #E8DFD5;
|
||||
border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,0.12);
|
||||
padding:16px;
|
||||
"
|
||||
>
|
||||
<p style="font-size:14px;font-weight:600;color:#2C1810;margin:0 0 4px;">Share feedback</p>
|
||||
<p style="font-size:12px;color:#78716C;margin:0 0 12px;">What's on your mind?</p>
|
||||
<form
|
||||
hx-post="{{ url_for('public.feedback') }}"
|
||||
hx-target="#feedback-result"
|
||||
hx-swap="innerHTML"
|
||||
hx-on::after-request="this.reset()"
|
||||
>
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<input type="hidden" name="page_url" id="feedback-page-url" value="">
|
||||
<textarea
|
||||
name="message"
|
||||
placeholder="Tell us what you think..."
|
||||
required
|
||||
maxlength="2000"
|
||||
style="
|
||||
width:100%;box-sizing:border-box;resize:vertical;min-height:80px;
|
||||
border:1px solid #E8DFD5;border-radius:6px;padding:8px 10px;
|
||||
font-size:13px;color:#2C1810;outline:none;font-family:inherit;
|
||||
transition:border-color 0.15s;
|
||||
"
|
||||
onfocus="this.style.borderColor='#B45309'"
|
||||
onblur="this.style.borderColor='#E8DFD5'"
|
||||
></textarea>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:8px;">
|
||||
<div id="feedback-result" style="font-size:12px;"></div>
|
||||
<button
|
||||
type="submit"
|
||||
style="
|
||||
background:#B45309;color:#fff;border:none;border-radius:6px;
|
||||
padding:6px 14px;font-size:13px;font-weight:600;cursor:pointer;
|
||||
transition:background 0.15s;flex-shrink:0;
|
||||
"
|
||||
onmouseover="this.style.background='#92400E'"
|
||||
onmouseout="this.style.background='#B45309'"
|
||||
>Send</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#feedback-popover.open { display: block; }
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var urlInput = document.getElementById('feedback-page-url');
|
||||
if (urlInput) urlInput.value = window.location.href;
|
||||
|
||||
document.addEventListener('click', function(e) {
|
||||
var widget = document.getElementById('feedback-widget');
|
||||
if (widget && !widget.contains(e.target)) {
|
||||
var popover = document.getElementById('feedback-popover');
|
||||
if (popover) popover.classList.remove('open');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% include "_feedback_widget.html" %}
|
||||
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user