Skip to content
Merged
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
10 changes: 5 additions & 5 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ class TestingConfig(Config):
class ProductionConfig(Config):
"""Production configuration"""
FLASK_DEBUG = False
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
REMEMBER_COOKIE_SECURE = True
# Honor environment configuration; default to enabled in production
# Honor environment with secure-by-default values in production
SESSION_COOKIE_SECURE = os.getenv('SESSION_COOKIE_SECURE', 'true').lower() == 'true'
SESSION_COOKIE_HTTPONLY = os.getenv('SESSION_COOKIE_HTTPONLY', 'true').lower() == 'true'
REMEMBER_COOKIE_SECURE = os.getenv('REMEMBER_COOKIE_SECURE', 'true').lower() == 'true'
WTF_CSRF_ENABLED = os.getenv('WTF_CSRF_ENABLED', 'true').lower() == 'true'
WTF_CSRF_SSL_STRICT = True
WTF_CSRF_SSL_STRICT = os.getenv('WTF_CSRF_SSL_STRICT', 'true').lower() == 'true'

# Configuration mapping
config = {
Expand Down
1 change: 1 addition & 0 deletions app/static/enhanced-ui.css
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@

.dark .toast {
background: #2d3748;
color: #E2E8F0; /* ensure readable text on dark background */
}

.toast.removing {
Expand Down
2 changes: 1 addition & 1 deletion app/static/form-bridge.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ textarea.form-control { min-height: 6rem; resize: vertical; }
/* =============================
Badge chips
============================= */
.chip { display: inline-flex; align-items: center; padding: 0.125rem 0.5rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 600; line-height: 1; border: 1px solid transparent; }
.chip { display: inline-flex; align-items: center; padding: 0.125rem 0.5rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 600; line-height: 1; border: 1px solid transparent; white-space: nowrap; }
.chip-neutral { background: #F1F5F9; color: #334155; }
.dark .chip-neutral { background: #1F2937; color: #E5E7EB; border-color: #374151; }
.chip-success { background: #DCFCE7; color: #166534; }
Expand Down
37 changes: 25 additions & 12 deletions app/static/smart-notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,18 +277,31 @@ class SmartNotificationManager {
try {
const response = await fetch('/api/summary/today');
const summary = await response.json();

this.show({
title: 'Daily Summary',
message: `Today you logged ${summary.hours}h across ${summary.projects} projects. Great work!`,
type: 'success',
priority: 'normal',
persistent: true,
actions: [
{ id: 'view-details', label: 'View Details' },
{ id: 'dismiss', label: 'Dismiss' }
]
});

const hours = (summary && typeof summary.hours === 'number')
? summary.hours
: (summary && summary.hours ? Number(summary.hours) : 0);
const projects = (summary && typeof summary.projects === 'number')
? summary.projects
: (summary && summary.projects ? Number(summary.projects) : 0);

// Build a safe, human-friendly message
const hoursText = isNaN(hours) ? '0' : String(hours);
const projectsText = isNaN(projects) ? '0' : String(projects);
const message = `Today you logged ${hoursText}h across ${projectsText} projects. Great work!`;

// Auto-dismiss after 8s; no permanent sticky summary to avoid lingering toasts
if (window.toastManager && typeof window.toastManager.show === 'function') {
window.toastManager.show(message, 'success', 8000);
} else {
this.show({
title: 'Daily Summary',
message,
type: 'success',
priority: 'normal',
persistent: false
});
}
} catch (error) {
console.error('Error fetching daily summary:', error);
}
Expand Down
6 changes: 3 additions & 3 deletions app/templates/projects/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ <h3 class="text-lg font-semibold mb-4">{{ _('Tasks for this project') }}</h3>
'medium':'bg-sky-100 text-sky-700 dark:bg-sky-900/30 dark:text-sky-300',
'high':'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
'urgent':'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300'}[p] if p in ['low','medium','high','urgent'] else 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300' %}
<span class="px-2 py-1 rounded-full text-xs font-medium {{ pcls }}">{{ task.priority_display }}</span>
<span class="px-2 py-1 rounded-full text-xs font-medium whitespace-nowrap {{ pcls }}">{{ task.priority_display }}</span>
</td>
<td class="p-3">
{% set s = task.status %}
Expand All @@ -90,12 +90,12 @@ <h3 class="text-lg font-semibold mb-4">{{ _('Tasks for this project') }}</h3>
'review':'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
'done':'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300',
'cancelled':'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-200'}[s] if s in ['todo','in_progress','review','done','cancelled'] else 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300' %}
<span class="px-2 py-1 rounded-full text-xs font-medium {{ scls }}">{{ task.status_display }}</span>
<span class="px-2 py-1 rounded-full text-xs font-medium whitespace-nowrap {{ scls }}">{{ task.status_display }}</span>
</td>
<td class="p-3">
{% if task.due_date %}
{% set overdue = task.is_overdue %}
<span class="px-2 py-1 rounded-md text-xs font-medium {{ 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300' if overdue else 'bg-primary/10 text-primary' }}">{{ task.due_date.strftime('%Y-%m-%d') }}</span>
<span class="px-2 py-1 rounded-md text-xs font-medium whitespace-nowrap {{ 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300' if overdue else 'bg-primary/10 text-primary' }}">{{ task.due_date.strftime('%Y-%m-%d') }}</span>
{% else %}
<span class="text-text-muted-light dark:text-text-muted-dark">—</span>
{% endif %}
Expand Down
1 change: 1 addition & 0 deletions app/templates/tasks/_kanban.html
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ <h6 class="kanban-card-title">
font-weight: 600;
letter-spacing: 0.02em;
text-transform: uppercase;
white-space: nowrap;
}

.kanban-badge i {
Expand Down
2 changes: 1 addition & 1 deletion app/templates/tasks/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ <h6 class="font-semibold flex items-center gap-2"><i class="fas fa-edit text-yel
{{ task.priority_display }}
</span>
<span id="statusPreview" class="status-badge status-{{ task.status }}">
{{ task.status_display }}
<span class="whitespace-nowrap">{{ task.status_display }}</span>
</span>
</div>

Expand Down
6 changes: 3 additions & 3 deletions app/templates/tasks/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ <h3 class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">
'medium':'bg-sky-100 text-sky-700 dark:bg-sky-900/30 dark:text-sky-300',
'high':'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
'urgent':'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300'}[p] if p in ['low','medium','high','urgent'] else 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300' %}
<span class="px-2 py-1 rounded-full text-xs font-medium {{ pcls }}">{{ task.priority_display }}</span>
<span class="px-2 py-1 rounded-full text-xs font-medium whitespace-nowrap {{ pcls }}">{{ task.priority_display }}</span>
</td>
<td class="p-4">
{% set s = task.status %}
Expand All @@ -136,12 +136,12 @@ <h3 class="text-sm font-medium text-text-muted-light dark:text-text-muted-dark">
'review':'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
'done':'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300',
'cancelled':'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-200'}[s] if s in ['todo','in_progress','review','done','cancelled'] else 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300' %}
<span class="px-2 py-1 rounded-full text-xs font-medium {{ scls }}">{{ task.status_display }}</span>
<span class="px-2 py-1 rounded-full text-xs font-medium whitespace-nowrap {{ scls }}">{{ task.status_display }}</span>
</td>
<td class="p-4 table-number">
{% if task.due_date %}
{% set overdue = task.is_overdue %}
<span class="chip {{ 'chip-danger' if overdue else 'chip-neutral' }}">{{ task.due_date.strftime('%Y-%m-%d') }}</span>
<span class="chip whitespace-nowrap {{ 'chip-danger' if overdue else 'chip-neutral' }}">{{ task.due_date.strftime('%Y-%m-%d') }}</span>
{% else %}
<span class="text-text-muted-light dark:text-text-muted-dark">—</span>
{% endif %}
Expand Down
8 changes: 2 additions & 6 deletions app/templates/tasks/my_tasks.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,8 @@ <h6 class="mb-0">
<div class="card-header border-0 pb-0">
<div class="d-flex justify-content-between align-items-start mb-2">
<div class="d-flex align-items-center">
<span class="status-badge status-{{ task.status }} me-2">
{{ task.status_display }}
</span>
<span class="priority-badge priority-{{ task.priority }}">
{{ task.priority_display }}
</span>
<span class="status-badge status-{{ task.status }} me-2"><span class="whitespace-nowrap">{{ task.status_display }}</span></span>
<span class="priority-badge priority-{{ task.priority }}"><span class="whitespace-nowrap">{{ task.priority_display }}</span></span>
</div>
<div class="dropdown">
<button class="btn btn-sm btn-outline-secondary border-0" type="button" data-bs-toggle="dropdown">
Expand Down
2 changes: 1 addition & 1 deletion app/templates/tasks/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ <h1 class="text-2xl font-bold">{{ task.name }}</h1>
{% endif %}
</div>

<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Left Column: Task Details -->
<div class="lg:col-span-2 space-y-6">
{% if task.description %}
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

setup(
name='timetracker',
version='3.2.1',
version='3.2.2',
packages=find_packages(),
include_package_data=True,
install_requires=[
Expand Down
Loading