mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-05 19:20:21 -06:00
- 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.
216 lines
7.3 KiB
Bash
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()"
|