🚀 Major improvements: Fix short URLs, separate public/admin views, and enhance UX

 Fixed Critical Issues:
- Fixed dynamic QR code short URL redirect functionality
- Resolved data consistency issues with multiple LinkPageManager instances
- Fixed worker concurrency problems in Gunicorn configuration

🎨 UI/UX Enhancements:
- Separated public page from admin statistics view
- Created clean public_page.html for QR code users (no admin info)
- Added comprehensive statistics_page.html for admin analytics
- Enhanced dashboard with separate 'Manage' and 'Stats' buttons
- Improved navigation flow throughout the application

🔧 Technical Improvements:
- Added URLShortener instance reloading for data consistency
- Reduced Gunicorn workers to 1 to prevent file conflicts
- Increased timeout to 60s for better performance
- Enhanced debug logging for troubleshooting
- Added proper error handling and 404 responses

📁 New Files:
- app/templates/public_page.html - Clean public interface
- app/templates/statistics_page.html - Admin analytics dashboard

�� Modified Files:
- app/routes/main.py - Added /stats route, improved short URL handling
- app/templates/edit_links.html - Added Statistics button
- app/templates/index.html - Added Stats button for QR codes
- app/utils/link_manager.py - Enhanced data reloading
- app/utils/url_shortener.py - Added debug logging
- gunicorn.conf.py - Optimized worker configuration

This update provides a professional separation between public content and admin functionality while ensuring reliable short URL operation.
This commit is contained in:
2025-07-18 09:21:36 -04:00
parent 1ae080df37
commit 53f5c513d4
11 changed files with 920 additions and 8 deletions

View File

@@ -216,26 +216,34 @@ def upload_logo():
def create_link_page():
"""Create a new dynamic link page and QR code"""
try:
print("DEBUG: Starting create_link_page")
data = request.json
title = data.get('title', 'My Links')
description = data.get('description', 'Collection of useful links')
print(f"DEBUG: Creating link page with title='{title}', description='{description}'")
# Create the link page
page_id = link_manager.create_link_page(title, description)
print(f"DEBUG: Created link page with ID: {page_id}")
# Create the original page URL
original_page_url = f"{request.url_root}links/{page_id}"
print(f"DEBUG: Original page URL: {original_page_url}")
# Automatically create a short URL for the link page
print(f"DEBUG: Creating short URL for: {original_page_url}")
short_result = link_manager.create_standalone_short_url(
original_page_url,
title=f"Link Page: {title}",
custom_code=None
)
print(f"DEBUG: Short URL result: {short_result}")
short_page_url = short_result['short_url']
# Store the short URL info with the page
print(f"DEBUG: Setting page short URL: {short_page_url}, code: {short_result['short_code']}")
link_manager.set_page_short_url(page_id, short_page_url, short_result['short_code'])
print(f"DEBUG: Page short URL set successfully")
settings = {
'size': data.get('size', 10),
@@ -281,7 +289,10 @@ def create_link_page():
def add_link_to_page(page_id):
"""Add a link to a page"""
try:
print(f"DEBUG: Adding link to page {page_id}")
data = request.json
print(f"DEBUG: Request data: {data}")
title = data.get('title', '')
url = data.get('url', '')
description = data.get('description', '')
@@ -289,8 +300,10 @@ def add_link_to_page(page_id):
custom_short_code = data.get('custom_short_code', None)
if not title or not url:
print("DEBUG: Missing title or URL")
return jsonify({'error': 'Title and URL are required'}), 400
print(f"DEBUG: Calling link_manager.add_link with shortener={enable_shortener}")
success = link_manager.add_link(
page_id, title, url, description,
enable_shortener=enable_shortener,
@@ -298,11 +311,14 @@ def add_link_to_page(page_id):
)
if success:
print("DEBUG: Link added successfully")
return jsonify({'success': True})
else:
print(f"DEBUG: Failed to add link - page {page_id} not found")
return jsonify({'error': 'Page not found'}), 404
except Exception as e:
print(f"DEBUG: Exception in add_link_to_page: {e}")
return jsonify({'error': str(e)}), 500
@bp.route('/link_pages/<page_id>/links/<link_id>', methods=['PUT'])

View File

@@ -5,6 +5,7 @@ Main routes for QR Code Manager
from flask import Blueprint, render_template, redirect, abort
from app.utils.auth import login_required
from app.utils.link_manager import LinkPageManager
from app.utils.url_shortener import URLShortener
bp = Blueprint('main', __name__)
@@ -19,14 +20,24 @@ def index():
@bp.route('/links/<page_id>')
def view_link_page(page_id):
"""Display the public link page"""
"""Display the public link page (for QR codes)"""
if not link_manager.page_exists(page_id):
return "Page not found", 404
link_manager.increment_view_count(page_id)
page_data = link_manager.get_page(page_id)
return render_template('link_page.html', page=page_data)
return render_template('public_page.html', page=page_data)
@bp.route('/stats/<page_id>')
@login_required
def view_page_statistics(page_id):
"""Display the statistics page for admins"""
if not link_manager.page_exists(page_id):
return "Page not found", 404
page_data = link_manager.get_page(page_id)
return render_template('statistics_page.html', page=page_data)
@bp.route('/edit/<page_id>')
@login_required
@@ -48,6 +59,8 @@ def health_check():
@bp.route('/s/<short_code>')
def redirect_short_url(short_code):
"""Redirect short URL to original URL"""
# Force reload of data to ensure we have the latest short URLs
link_manager.url_shortener = URLShortener()
original_url = link_manager.resolve_short_url(short_code)
if original_url:
return redirect(original_url)