Files
TimeTrack/templates/layout.html

289 lines
15 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }} - {{ g.branding.app_name if g.branding else 'TimeTrack' }}{% if g.company %} - {{ g.company.name }}{% endif %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/fonts.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/icons@latest/iconfont/tabler-icons.min.css">
{% if not g.user %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/splash.css') }}">
{% endif %}
{% if g.branding and g.branding.favicon_filename %}
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='uploads/branding/' + g.branding.favicon_filename) }}">
{% endif %}
<style>
:root {
--primary-color: {{ g.branding.primary_color if g.branding else '#007bff' }};
}
.btn-primary {
background-color: var(--primary-color);
border-color: var(--primary-color);
}
.btn-primary:hover {
background-color: {{ (g.branding.primary_color if g.branding else '#007bff') + 'dd' }};
border-color: {{ (g.branding.primary_color if g.branding else '#007bff') + 'dd' }};
}
.nav-icon {
color: rgb(116, 85, 175) /* var(--primary-color); */
}
a:hover {
color: var(--primary-color);
}
.mobile-logo {
max-height: 30px;
max-width: 150px;
object-fit: contain;
}
.sidebar-logo {
max-height: 32px;
max-width: 160px;
object-fit: contain;
}
.mobile-nav-brand a {
display: flex;
align-items: center;
}
.sidebar-header h2 a {
display: flex;
align-items: center;
color: inherit;
text-decoration: none;
}
</style>
</head>
<body{% if g.user %} class="has-user"{% endif %}>
<!-- Mobile header -->
{% if g.user %}
<header class="mobile-header">
<div class="mobile-nav-brand">
<a href="{{ url_for('home') }}">
{% if g.branding and g.branding.logo_filename %}
<img src="{{ url_for('static', filename='uploads/branding/' + g.branding.logo_filename) }}"
alt="{{ g.branding.logo_alt_text }}"
class="mobile-logo">
{% else %}
{{ g.branding.app_name if g.branding else 'TimeTrack' }}
{% endif %}
</a>
</div>
<button class="mobile-nav-toggle" id="mobile-nav-toggle">
<span></span>
<span></span>
<span></span>
</button>
</header>
{% endif %}
<!-- Sidebar navigation -->
{% if g.user %}
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<!-- <h2>
<a href="{{ url_for('home') }}">
{% if g.branding and g.branding.logo_filename %}
<img src="{{ url_for('static', filename='uploads/branding/' + g.branding.logo_filename) }}"
alt="{{ g.branding.logo_alt_text }}"
class="sidebar-logo">
{% else %}
{{ g.branding.app_name if g.branding else 'TimeTrack' }}
{% endif %}
</a>
-->
</h2>
<button class="sidebar-toggle" id="sidebar-toggle">
<span></span>
<span></span>
<span></span>
</button>
{% if g.user %}
<!-- User Account Menu -->
<a href="#" class="user-dropdown-toggle" id="user-dropdown-toggle" data-tooltip="{{ g.user.username }}">
<img src="{{ g.user.get_avatar_url(32) }}" alt="{{ g.user.username }}" class="user-avatar">
<span class="nav-text">{{ g.user.username }}<span class="dropdown-arrow"></span></span>
</a>
<!-- User Dropdown Context Menu -->
<div class="user-dropdown-modal" id="user-dropdown-modal">
<div class="user-dropdown-header">
<img src="{{ g.user.get_avatar_url(64) }}" alt="{{ g.user.username }}" class="user-avatar-large">
<h3>{{ g.user.username }}</h3>
<div class="user-info">
{% if g.user.email %}
{{ g.user.email }}
{% endif %}
</div>
</div>
<div class="user-dropdown-menu">
<ul>
<li><a href="{{ url_for('profile') }}"><i class="nav-icon ti ti-user"></i>Profile</a></li>
<li><a href="{{ url_for('config') }}"><i class="nav-icon ti ti-settings"></i>Settings</a></li>
<li class="user-dropdown-divider"></li>
<li><a href="{{ url_for('logout') }}"><i class="nav-icon ti ti-logout"></i>Logout</a></li>
</ul>
</div>
</div>
{% endif %}
</div>
<nav class="sidebar-nav">
<ul>
{% if g.user %}
<li><a href="{{ url_for('home') }}" data-tooltip="Home"><i class="nav-icon ti ti-home"></i><span class="nav-text">Home</span></a></li>
<li><a href="{{ url_for('time_tracking') }}" data-tooltip="Time Tracking"><i class="nav-icon ti ti-clock"></i><span class="nav-text">Time Tracking</span></a></li>
<li><a href="{{ url_for('dashboard') }}" data-tooltip="Dashboard"><i class="nav-icon ti ti-dashboard"></i><span class="nav-text">Dashboard</span></a></li>
<li><a href="{{ url_for('tasks.unified_task_management') }}" data-tooltip="Task Management"><i class="nav-icon ti ti-clipboard-list"></i><span class="nav-text">Task Management</span></a></li>
<li><a href="{{ url_for('sprints.sprint_management') }}" data-tooltip="Sprint Management"><i class="nav-icon ti ti-run"></i><span class="nav-text">Sprints</span></a></li>
<li><a href="{{ url_for('notes.notes_list') }}" data-tooltip="Notes"><i class="nav-icon ti ti-notes"></i><span class="nav-text">Notes</span></a></li>
<li><a href="{{ url_for('analytics') }}" data-tooltip="Time Analytics"><i class="nav-icon ti ti-chart-bar"></i><span class="nav-text">Analytics</span></a></li>
<!-- Role-based menu items -->
{% if g.user.role == Role.ADMIN or g.user.role == Role.SYSTEM_ADMIN %}
<li class="nav-divider">Admin</li>
<li><a href="{{ url_for('companies.admin_company') }}" data-tooltip="Company Settings"><i class="nav-icon ti ti-building"></i><span class="nav-text">Company Settings</span></a></li>
<li><a href="{{ url_for('users.admin_users') }}" data-tooltip="Manage Users"><i class="nav-icon ti ti-users"></i><span class="nav-text">Manage Users</span></a></li>
<li><a href="{{ url_for('invitations.list_invitations') }}" data-tooltip="Invitations"><i class="nav-icon ti ti-mail"></i><span class="nav-text">Invitations</span></a></li>
<li><a href="{{ url_for('teams.admin_teams') }}" data-tooltip="Manage Teams"><i class="nav-icon ti ti-users-group"></i><span class="nav-text">Manage Teams</span></a></li>
<li><a href="{{ url_for('projects.admin_projects') }}" data-tooltip="Manage Projects"><i class="nav-icon ti ti-folder"></i><span class="nav-text">Manage Projects</span></a></li>
{% if g.user.role == Role.SYSTEM_ADMIN %}
<li class="nav-divider">System Admin</li>
<li><a href="{{ url_for('system_admin.system_admin_dashboard') }}" data-tooltip="System Dashboard"><i class="nav-icon ti ti-world"></i><span class="nav-text">System Dashboard</span></a></li>
<li><a href="{{ url_for('announcements.index') }}" data-tooltip="Announcements"><i class="nav-icon ti ti-speakerphone"></i><span class="nav-text">Announcements</span></a></li>
{% endif %}
{% elif g.user.role in [Role.TEAM_LEADER, Role.SUPERVISOR] %}
<li class="nav-divider">Team</li>
<li><a href="{{ url_for('dashboard') }}" data-tooltip="Dashboard"><i class="nav-icon ti ti-chart-line"></i><span class="nav-text">Dashboard</span></a></li>
{% if g.user.role == Role.SUPERVISOR %}
<li><a href="{{ url_for('projects.admin_projects') }}" data-tooltip="Manage Projects"><i class="nav-icon ti ti-folder"></i><span class="nav-text">Manage Projects</span></a></li>
{% endif %}
{% endif %}
{% else %}
<li><a href="{{ url_for('about') }}" data-tooltip="About"><i class="nav-icon ti ti-info-circle"></i><span class="nav-text">About</span></a></li>
<li><a href="{{ url_for('login') }}" data-tooltip="Login"><i class="nav-icon ti ti-key"></i><span class="nav-text">Login</span></a></li>
<li><a href="{{ url_for('register') }}" data-tooltip="Register"><i class="nav-icon ti ti-user-plus"></i><span class="nav-text">Register</span></a></li>
{% endif %}
</ul>
</nav>
</aside>
{% endif %}
<!-- Mobile overlay -->
{% if g.user %}
<div class="mobile-overlay" id="mobile-overlay"></div>
{% endif %}
<main class="main-content">
<!-- System Announcements -->
{% if active_announcements %}
<div class="announcements">
{% for announcement in active_announcements %}
<div class="alert alert-{{ announcement.announcement_type }}{% if announcement.is_urgent %} alert-urgent{% endif %}">
<div class="announcement-header">
<strong>{{ announcement.title }}</strong>
{% if announcement.is_urgent %}
<span class="urgent-badge">URGENT</span>
{% endif %}
</div>
<div class="announcement-content">
{{ announcement.content|safe }}
</div>
{% if announcement.created_at %}
<small class="announcement-date">
Posted: {{ announcement.created_at.strftime('%Y-%m-%d %H:%M') }}
</small>
{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<div class="flash-messages">
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<!-- Email Nag Screens -->
{% if g.show_email_nag %}
<div class="email-nag-banner">
<div class="email-nag-content">
<span class="email-nag-icon"><i class="ti ti-mail"></i></span>
<span class="email-nag-text">
<strong>Add your email address</strong> to enable account recovery and receive important notifications.
</span>
<a href="{{ url_for('profile') }}" class="btn btn-sm btn-primary">Add Email</a>
<button class="email-nag-dismiss" onclick="dismissEmailNag()" title="Dismiss for this session">×</button>
</div>
</div>
{% elif g.show_email_verification_nag %}
<div class="email-nag-banner email-verify">
<div class="email-nag-content">
<span class="email-nag-icon"><i class="ti ti-mail-opened"></i></span>
<span class="email-nag-text">
<strong>Please verify your email address</strong> to ensure you can recover your account if needed.
</span>
<a href="{{ url_for('profile') }}" class="btn btn-sm btn-warning">Verify Email</a>
<button class="email-nag-dismiss" onclick="dismissEmailNag()" title="Dismiss for this session">×</button>
</div>
</div>
{% endif %}
{% block content %}{% endblock %}
</main>
<footer class="site-footer">
<div class="footer-content">
<div class="footer-info">
<p>&copy; {{ current_year }} {{ g.branding.app_name if g.branding else 'TimeTrack' }}{% if g.company %} - {{ g.company.name }}{% endif %}. All rights reserved.</p>
</div>
<div class="footer-links">
<a href="{{ url_for('about') }}">About</a>
{% if g.branding and g.branding.imprint_enabled %}
<span class="footer-separator"></span>
<a href="{{ url_for('imprint') }}">{{ g.branding.imprint_title or 'Imprint' }}</a>
{% endif %}
</div>
</div>
</footer>
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
<script src="{{ url_for('static', filename='js/sidebar.js') }}"></script>
<script src="{{ url_for('static', filename='js/password-strength.js') }}"></script>
{% if g.user %}
<script src="{{ url_for('static', filename='js/user-dropdown.js') }}"></script>
<script>
function dismissEmailNag() {
// Hide the banner with animation
const banner = document.querySelector('.email-nag-banner');
if (banner) {
banner.style.animation = 'slideUp 0.3s ease-out';
setTimeout(() => {
banner.style.display = 'none';
}, 300);
}
// Store in session storage to not show again this session
sessionStorage.setItem('emailNagDismissed', 'true');
}
// Check if already dismissed this session
if (sessionStorage.getItem('emailNagDismissed') === 'true') {
const banner = document.querySelector('.email-nag-banner');
if (banner) {
banner.style.display = 'none';
}
}
</script>
{% else %}
<script src="{{ url_for('static', filename='js/splash.js') }}"></script>
{% endif %}
<!-- Custom Tracking Script -->
{% if tracking_script_enabled and tracking_script_code %}
{{ tracking_script_code|safe }}
{% endif %}
</body>
</html>