diff --git a/README.md b/README.md index 0e2b5d0..7aaed92 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ A Flask-based web application for viewing and analyzing QC reports stored in Box - Parsed Data View: Structured display of check results with filtering - Embedded Reports: View original HTML reports inline - **Aggregated Summary**: Overview of all checks across multiple files +- **Quick Navigation**: Click "View Details" link next to error files to jump directly to that report +- **HTML Export Options**: + - Export Combined Report: All reports in a single HTML file + - Export Error Reports Only: Filter to only files with errors - **PDF Export**: Export combined reports as a single PDF document (requires WeasyPrint setup) - **Error Highlighting**: Quickly identify files with errors - **User Session Management**: httpOnly cookies with automatic logout @@ -206,7 +210,8 @@ web_hm_ai_qc_report/ The dashboard shows: - **Summary**: Overall statistics (files checked, total checks, passed/errors/warnings) -- **Files with Errors**: Quick list of problematic files +- **Files with Errors**: Quick list of problematic files with "View Details" links + - Click the "View Details" link to jump directly to that report and see which checks failed - **Parsed Data View**: Structured check results with filtering options - **Embedded Reports**: Original HTML reports in iframes @@ -217,14 +222,28 @@ Use the filter buttons to view: - Only files with errors - Only files that passed all checks -### 5. Export to PDF +### 5. Export Reports -Click "Export Combined Report as PDF" to download a PDF containing: -- Overall summary -- All check results -- Detailed findings for each file +Two export options are available: -**Note**: PDF export requires WeasyPrint system dependencies (see Troubleshooting). +**Export Combined Report as HTML** (Green button): +- Downloads all reports in a single HTML file +- Includes all files (passed and failed) +- Can be converted to PDF using browser's Print function + +**Export Error Reports Only** (Red button): +- Only appears when there are files with errors +- Downloads only files that have errors +- Excludes files that passed all checks +- Filename includes "_ERRORS_ONLY_" suffix +- Shows warning banner indicating filtered content + +To convert HTML export to PDF: +1. Open the downloaded HTML file in your browser +2. Press Ctrl/Cmd + P to print +3. Select "Save as PDF" as the destination + +**Note**: Native PDF export requires WeasyPrint system dependencies (see Troubleshooting). ### 6. Sign Out @@ -243,7 +262,9 @@ Click the "Logout" button in the navbar to sign out. - `GET /dashboard/` - Dashboard for specific job - `GET /api/report/` - Get parsed report data (JSON) - `GET /api/report//raw` - Get raw HTML report -- `GET /export/pdf/` - Export combined PDF +- `GET /export/html/` - Export combined HTML report (all files) +- `GET /export/html//errors` - Export HTML report (error files only) +- `GET /export/pdf/` - Export combined PDF (requires WeasyPrint) ## Box Folder Structure @@ -474,6 +495,17 @@ For issues or questions, contact the development team. ## Version History +### v2.2.0 - Enhanced Navigation and Export (January 2026) +- **Added Quick Navigation**: "View Details" links next to error files for direct navigation + - Automatically switches to Parsed Data View tab + - Scrolls to and expands the specific report + - Highlights the report briefly for easy identification +- **Added Error-Only Export**: New export option to download only files with errors + - Separate red button appears when errors are present + - Filename includes "_ERRORS_ONLY_" suffix + - Export includes warning banner to indicate filtered content +- **Improved User Experience**: Streamlined workflow for reviewing and sharing error reports + ### v2.1.0 - CAMPAIGNS Folder Integration (December 2025) - **Updated folder structure** to support CAMPAIGNS/{CampaignNumber}/QC/ hierarchy - **Added real-time progress indicator** with status updates during search diff --git a/app.py b/app.py index 489c4cb..9a6a5c5 100644 --- a/app.py +++ b/app.py @@ -287,6 +287,81 @@ def export_html(job_number): return jsonify({'error': str(e)}), 500 +@app.route('/export/html//errors') +@auth.require_auth +def export_html_errors_only(job_number): + """ + Export error reports only as HTML. + + Args: + job_number: Job/reference number + + Returns: + HTML file download containing only reports with errors + """ + try: + logger.info(f"Exporting error reports only for job number: {job_number}") + + # Search for reports + box_client = get_box_client() + reports = box_client.search_by_job_number(job_number) + + if not reports: + return jsonify({'error': f'No reports found for job number: {job_number}'}), 404 + + # Download and parse reports + parsed_reports = [] + + for report_info in reports: + try: + content = box_client.download_file(report_info['id']) + html_content = content.decode('utf-8') + + parser = QCReportParser(html_content) + parsed_data = parser.parse() + parsed_data['html_content'] = html_content + + # Only include reports with errors + if parsed_data.get('summary', {}).get('error', 0) > 0: + parsed_reports.append(parsed_data) + + except Exception as e: + logger.error(f"Error parsing report for error export: {e}") + + # Check if any error reports were found + if not parsed_reports: + return jsonify({'error': f'No error reports found for job number: {job_number}'}), 404 + + # Generate aggregate summary (only for error reports) + aggregated = aggregate_reports(parsed_reports) + + # Render HTML template + html_string = render_template( + 'pdf_export.html', + job_number=job_number, + reports=parsed_reports, + aggregated=aggregated, + generated_at=datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + errors_only=True + ) + + # Generate filename + timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') + filename = f'QC_Report_{job_number}_ERRORS_ONLY_{timestamp}.html' + + # Return HTML as downloadable file + return send_file( + BytesIO(html_string.encode('utf-8')), + mimetype='text/html', + as_attachment=True, + download_name=filename + ) + + except Exception as e: + logger.error(f"Error exporting error reports: {e}") + return jsonify({'error': str(e)}), 500 + + @app.route('/health') def health(): """Health check endpoint.""" diff --git a/run.sh b/run.sh index 88713ed..ea1fe48 100755 --- a/run.sh +++ b/run.sh @@ -22,6 +22,6 @@ fi # Run Flask app echo "Starting Flask development server..." -echo "App will be available at: http://localhost:5000" +echo "App will be available at: http://localhost:7183" echo "" -python app.py +./venv/bin/python app.py diff --git a/templates/dashboard.html b/templates/dashboard.html index c0b50cd..de169a1 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -105,7 +105,12 @@
    {% for file in aggregated.files_with_errors %}
  • - {{ file.filename }} +
    + {{ file.filename }} + + View Details + +
    {{ file.error_count }} error(s)
  • {% endfor %} @@ -117,12 +122,17 @@ - +
    - + Export Combined Report as HTML + {% if aggregated.files_with_errors %} + + Export Error Reports Only + + {% endif %}
    @@ -163,7 +173,7 @@
    {% for report in reports %} -
    +