Files
TimeTracker/docker/start-new.sh
Dries Peeters d230a41e8a feat: enhance web interface layout and fix logo import circular dependency
- Improve web interface layout for better user-friendliness and mobile responsiveness
  * Update CSS variables for consistent spacing and component sizing
  * Enhance card layouts with improved padding, borders, and shadows
  * Optimize button and form element dimensions for better touch targets
  * Add hover effects and animations for improved user interaction
  * Implement responsive grid system with mobile-first approach

- Refactor mobile JavaScript to prevent duplicate initialization
  * Consolidate mobile enhancements into dedicated utility classes
  * Add initialization guards to prevent double loading
  * Implement MobileUtils and MobileNavigation classes
  * Remove duplicate event listeners and mobile enhancements

- Fix circular import issue in logo handling
  * Replace problematic 'from app import app' with Flask's current_app
  * Add error handling for cases where current_app is unavailable
  * Improve logo path resolution with fallback mechanisms
  * Fix settings model to use proper Flask context

- Clean up template code and remove duplication
  * Remove duplicate mobile enhancements from base template
  * Clean up dashboard template JavaScript
  * Centralize all mobile functionality in mobile.js
  * Add proper error handling and debugging

- Update CSS variables and spacing system
  * Introduce --section-spacing and --card-spacing variables
  * Add mobile-specific spacing variables
  * Improve border-radius and shadow consistency
  * Enhance typography and visual hierarchy

This commit resolves the double loading issue and logo import errors while
significantly improving the overall user experience and mobile responsiveness
of the web interface.
2025-08-30 10:09:06 +02:00

216 lines
7.3 KiB
Bash

#!/bin/bash
set -e
cd /app
export FLASK_APP=app
echo "=== Starting TimeTracker ==="
echo "Waiting for database to be ready..."
# Wait for Postgres to be ready
python - <<"PY"
import os
import time
import sys
from sqlalchemy import create_engine, text
from sqlalchemy.exc import OperationalError
url = os.getenv("DATABASE_URL", "")
if url.startswith("postgresql"):
for attempt in range(30):
try:
engine = create_engine(url, pool_pre_ping=True)
with engine.connect() as conn:
conn.execute(text("SELECT 1"))
print("Database connection established successfully")
break
except Exception as e:
print(f"Waiting for database... (attempt {attempt+1}/30): {e}")
time.sleep(2)
else:
print("Database not ready after waiting, exiting...")
sys.exit(1)
else:
print("No PostgreSQL database configured, skipping connection check")
PY
echo "=== FIXING DATABASE SCHEMA ==="
# Step 1: Create tasks table if it doesn't exist
echo "Step 1: Ensuring tasks table exists..."
python - <<"PY"
import os
import sys
from sqlalchemy import create_engine, text, inspect
url = os.getenv("DATABASE_URL", "")
if url.startswith("postgresql"):
try:
engine = create_engine(url, pool_pre_ping=True)
inspector = inspect(engine)
if 'tasks' not in inspector.get_table_names():
print("Creating tasks table...")
create_tasks_sql = """
CREATE TABLE tasks (
id SERIAL PRIMARY KEY,
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE NOT NULL,
name VARCHAR(200) NOT NULL,
description TEXT,
status VARCHAR(20) DEFAULT 'pending' NOT NULL,
priority VARCHAR(20) DEFAULT 'medium' NOT NULL,
assigned_to INTEGER REFERENCES users(id),
created_by INTEGER REFERENCES users(id) NOT NULL,
due_date DATE,
estimated_hours NUMERIC(5,2),
actual_hours NUMERIC(5,2),
started_at TIMESTAMP,
completed_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
"""
with engine.connect() as conn:
conn.execute(text(create_tasks_sql))
conn.commit()
print("✓ Tasks table created successfully")
else:
print("✓ Tasks table already exists")
except Exception as e:
print(f"Error creating tasks table: {e}")
sys.exit(1)
else:
print("No PostgreSQL database configured")
sys.exit(0)
PY
# Step 2: Add task_id column to time_entries if it doesn't exist
echo "Step 2: Ensuring task_id column exists in time_entries..."
python - <<"PY"
import os
import sys
from sqlalchemy import create_engine, text, inspect
url = os.getenv("DATABASE_URL", "")
if url.startswith("postgresql"):
try:
engine = create_engine(url, pool_pre_ping=True)
inspector = inspect(engine)
if 'time_entries' in inspector.get_table_names():
columns = inspector.get_columns("time_entries")
column_names = [col['name'] for col in columns]
print(f"Current columns in time_entries: {column_names}")
if 'task_id' not in column_names:
print("Adding task_id column...")
with engine.connect() as conn:
conn.execute(text("ALTER TABLE time_entries ADD COLUMN task_id INTEGER;"))
conn.commit()
print("✓ task_id column added successfully")
else:
print("✓ task_id column already exists")
else:
print("⚠ Warning: time_entries table does not exist")
except Exception as e:
print(f"Error adding task_id column: {e}")
sys.exit(1)
else:
print("No PostgreSQL database configured")
sys.exit(0)
PY
# Step 2.5: Add missing columns to tasks table if it exists
echo "Step 2.5: Ensuring tasks table has all required columns..."
python - <<"PY"
import os
import sys
from sqlalchemy import create_engine, text, inspect
url = os.getenv("DATABASE_URL", "")
if url.startswith("postgresql"):
try:
engine = create_engine(url, pool_pre_ping=True)
inspector = inspect(engine)
if 'tasks' in inspector.get_table_names():
columns = inspector.get_columns("tasks")
column_names = [col['name'] for col in columns]
print(f"Current columns in tasks: {column_names}")
# Check for missing columns
missing_columns = []
required_columns = ['started_at', 'completed_at']
for col in required_columns:
if col not in column_names:
missing_columns.append(col)
if missing_columns:
print(f"Adding missing columns to tasks table: {missing_columns}")
with engine.connect() as conn:
for col in missing_columns:
if col == 'started_at':
conn.execute(text("ALTER TABLE tasks ADD COLUMN started_at TIMESTAMP;"))
elif col == 'completed_at':
conn.execute(text("ALTER TABLE tasks ADD COLUMN completed_at TIMESTAMP;"))
conn.commit()
print("✓ Missing columns added to tasks table successfully")
else:
print("✓ tasks table has all required columns")
else:
print("⚠ Warning: tasks table does not exist")
except Exception as e:
print(f"Error adding missing columns to tasks: {e}")
sys.exit(1)
else:
print("No PostgreSQL database configured")
sys.exit(0)
PY
# Step 3: Run the main database initialization
echo "Step 3: Running main database initialization..."
python /app/docker/init-database.py
if [ $? -ne 0 ]; then
echo "Database initialization failed. Exiting."
exit 1
fi
# Step 4: Run the SQL database initialization (for invoice tables)
echo "Step 4: Running SQL database initialization..."
python /app/docker/init-database-sql.py
if [ $? -ne 0 ]; then
echo "SQL database initialization failed. Exiting."
exit 1
fi
# Step 5: Run company branding migration
echo "Step 5: Running company branding migration..."
python /app/docker/migrate-add-company-branding.py
if [ $? -ne 0 ]; then
echo "Company branding migration failed. Exiting."
exit 1
fi
# Step 6: Test system packages
echo "Step 6: Testing system packages..."
python /app/docker/test-packages.py
echo "Package test completed"
# Step 7: Test PDF generation capabilities
echo "Step 7: Testing PDF generation..."
python /app/docker/test-pdf-generation.py
echo "PDF generation test completed (warnings are normal if WeasyPrint dependencies missing)"
# Step 8: Test invoice routing
echo "Step 8: Testing invoice routing..."
python /app/docker/test-routing.py
echo "Routing test completed"
echo "=== DATABASE SCHEMA FIXED SUCCESSFULLY ==="
echo "Starting application..."
exec gunicorn --bind 0.0.0.0:8080 --worker-class eventlet --workers 1 --timeout 120 "app:create_app()"