Bug fixes, profile updates, report updates
96
CLAUDE.md
|
|
@ -4,14 +4,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
|
||||
## Project Overview
|
||||
|
||||
Visual AI QC is a Python Flask-based AI-powered quality control platform for analyzing marketing materials and design assets using OpenAI GPT-4 and Google Gemini models. It evaluates visual content against brand guidelines and design best practices through 34+ specialized QC checks.
|
||||
Visual AI QC is a Python Flask-based AI-powered quality control platform for analyzing marketing materials and design assets using OpenAI GPT-4 and Google Gemini models. It evaluates visual content against brand guidelines and design best practices through 33 specialized QC checks across 6 focused profiles.
|
||||
|
||||
## Core Architecture
|
||||
|
||||
### Main Components
|
||||
|
||||
- **`api_server.py`** - Main Flask server with async processing and parallel execution
|
||||
- **`visual_qc_apps/`** - Modular QC check system with 34+ individual check modules
|
||||
- **`visual_qc_apps/`** - Modular QC check system with 33 individual check modules
|
||||
- **`profiles/`** - JSON configuration files defining QC check combinations and weights
|
||||
- **`brand_guidelines/`** - Reference asset storage and brand guideline database
|
||||
- **`llm_config.py`** - Centralized LLM configuration and API interaction
|
||||
|
|
@ -69,9 +69,13 @@ python -c "import api_server, llm_config, profile_config"
|
|||
│ ├── utils.py # Shared utilities
|
||||
│ ├── flask_app_template.py # Template for new checks
|
||||
│ └── {check_name}/app.py # Individual QC checks
|
||||
├── profiles/ # QC profile configurations
|
||||
│ ├── default.json # All checks profile
|
||||
│ └── {brand_name}.json # Brand-specific profiles
|
||||
├── profiles/ # QC profile configurations (6 total)
|
||||
│ ├── general_check.json # General purpose profile (10 checks)
|
||||
│ ├── unilever_key_visual.json # Unilever key visual profile (15 checks)
|
||||
│ ├── unilever_packaging.json # Unilever packaging profile (17 checks)
|
||||
│ ├── diageo_key_visual.json # Diageo key visual profile (11 checks)
|
||||
│ ├── diageo_packaging.json # Diageo packaging profile (13 checks)
|
||||
│ └── inclusive_accessibility.json # Accessibility profile (2 checks)
|
||||
├── brand_guidelines/ # Reference assets
|
||||
│ └── guidelines_db.json # Asset metadata
|
||||
├── uploads/ # Temporary file uploads
|
||||
|
|
@ -159,6 +163,49 @@ The following API endpoints require authentication:
|
|||
- **Secure Headers**: Cookies use Secure, SameSite=Lax flags
|
||||
- **Server-side Validation**: No client-side security dependencies
|
||||
|
||||
## QC Profile System
|
||||
|
||||
### Available Profiles
|
||||
|
||||
The system includes 6 focused QC profiles designed for different use cases:
|
||||
|
||||
1. **General Check** (10 checks, 100-point scale)
|
||||
- Purpose: Streamlined general-purpose QC analysis
|
||||
- Checks: Essential design and technical standards
|
||||
- Weighting: Even distribution (10% each)
|
||||
- Requirements: No reference assets needed
|
||||
- Scoring: Individual scores 1-10, final score 0-100
|
||||
|
||||
2. **Unilever Key Visual** (15 checks, 120-point scale)
|
||||
- Purpose: Unilever brand guidelines for key visual materials
|
||||
- Special Logic: Bonus checks with zero-scoring for missing elements
|
||||
- Requirements: Brand guidelines recommended
|
||||
- Scoring: Weighted distribution, 120-point maximum
|
||||
|
||||
3. **Unilever Packaging** (17 checks)
|
||||
- Purpose: Unilever packaging design standards
|
||||
- Requirements: Brand guidelines recommended
|
||||
|
||||
4. **Diageo Key Visual** (11 checks)
|
||||
- Purpose: Diageo brand guidelines for key visuals
|
||||
- Requirements: Brand guidelines recommended
|
||||
|
||||
5. **Diageo Packaging** (13 checks)
|
||||
- Purpose: Diageo packaging design standards
|
||||
- Requirements: Brand guidelines recommended
|
||||
|
||||
6. **Inclusive Accessibility** (2 checks)
|
||||
- Purpose: Focused accessibility compliance
|
||||
- Checks: Accessibility and inclusive design
|
||||
- Requirements: No reference assets needed
|
||||
|
||||
### Profile Selection Guidelines
|
||||
|
||||
- **General content analysis**: Use General Check
|
||||
- **Brand-specific analysis**: Use appropriate brand profile
|
||||
- **Accessibility focus**: Use Inclusive Accessibility
|
||||
- **Mixed requirements**: Profiles can be combined in multi-profile analysis
|
||||
|
||||
## Recent System Enhancements
|
||||
|
||||
### Unilever Profile-Specific Scoring Logic
|
||||
|
|
@ -186,6 +233,29 @@ if (profile_config and profile_config.get('name') == 'Unilever Key Visual' and
|
|||
|
||||
This ensures that missing critical elements (faces, "new" text) result in zero scores, providing more stringent quality control for Unilever key visual assets.
|
||||
|
||||
### Scoring System Enhancements
|
||||
The scoring calculation system has been improved to handle different profile weight structures correctly:
|
||||
|
||||
#### Multi-Scale Scoring Support
|
||||
- **100-Point Scale**: General Check profile with total weight 10.0 uses direct weighted scores
|
||||
- **Other Scales**: Profiles with lower total weights use scaled scoring (weighted_score × 10)
|
||||
- **Brand-Specific Scales**: Unilever Key Visual uses 120-point maximum scale
|
||||
|
||||
#### Fixed Calculation Logic (`api_server.py`)
|
||||
```python
|
||||
# Smart scoring calculation based on profile weight structure
|
||||
if total_weight >= 10.0:
|
||||
overall_score = total_weighted_score # Direct score for high-weight profiles
|
||||
else:
|
||||
overall_score = total_weighted_score * 10 # Scale up for traditional profiles
|
||||
```
|
||||
|
||||
#### JSON Response Merging
|
||||
Enhanced JSON extraction to merge multiple JSON blocks from LLM responses:
|
||||
- Combines metadata (face_present, new_present) with scoring data
|
||||
- Enables proper bonus check logic for Unilever profiles
|
||||
- Maintains backward compatibility with single JSON responses
|
||||
|
||||
### Enhanced Saved Files Management
|
||||
The output file system has been significantly improved for better user experience:
|
||||
|
||||
|
|
@ -242,7 +312,19 @@ Before ending any session, ALWAYS run these Python syntax and import checks:
|
|||
2. **Import Check**: Run `python -c "import api_server, llm_config, profile_config"` to verify core modules import successfully
|
||||
3. **Authentication Check**: Run `python -c "import jwt_validator, auth_middleware; print('Authentication modules imported successfully')"` to verify authentication system
|
||||
4. **QC Module Check**: Test import of any modified QC modules in `visual_qc_apps/`
|
||||
5. **Enhanced System Check**: Verify recent enhancements work correctly:
|
||||
5. **Profile System Check**: Verify all 6 profiles load correctly:
|
||||
```bash
|
||||
python -c "
|
||||
from profile_config import get_profile
|
||||
profiles = ['general_check', 'unilever_key_visual', 'unilever_packaging', 'diageo_key_visual', 'diageo_packaging', 'inclusive_accessibility']
|
||||
for p in profiles:
|
||||
profile = get_profile(p)
|
||||
print(f'✅ {profile.name} ({len(profile.get_enabled_checks())} checks)')
|
||||
"
|
||||
```
|
||||
6. **Enhanced System Check**: Verify recent enhancements work correctly:
|
||||
- Test General Check profile 100-point scoring system
|
||||
- Test Unilever profile zero-scoring logic with face/new visibility checks
|
||||
- Test saved files auto-refresh and date sorting functionality
|
||||
- Test MSAL authentication initialization and error handling
|
||||
- Test MSAL authentication initialization and error handling
|
||||
- Verify scoring calculation handles different weight structures correctly
|
||||
80
README.md
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
## 🚀 Overview
|
||||
|
||||
Visual AI QC is an intelligent quality control platform that uses advanced AI (OpenAI GPT-4 and Google Gemini) to automatically analyze visual content against brand guidelines, technical specifications, and design best practices. The system provides comprehensive feedback, scoring, and recommendations for improving visual assets.
|
||||
Visual AI QC is an intelligent quality control platform that uses advanced AI (OpenAI GPT-4 and Google Gemini) to automatically analyze visual content against brand guidelines, technical specifications, and design best practices. The system provides comprehensive feedback, scoring, and recommendations for improving visual assets across 33 specialized QC checks and 6 focused profiles.
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
|
|
@ -24,7 +24,27 @@ Visual AI QC is an intelligent quality control platform that uses advanced AI (O
|
|||
|
||||
## 🆕 Recent Improvements
|
||||
|
||||
### **December 2024 - Latest Enhancements** 🚀
|
||||
### **August 2025 - Major System Overhaul** 🚀
|
||||
|
||||
#### **Streamlined Profile System** 📊
|
||||
- **Consolidated Profiles**: Reduced from 8+ profiles to 6 focused, purpose-built profiles
|
||||
- **General Check Profile**: New streamlined 10-check profile for general-purpose analysis
|
||||
- **100-Point Scoring**: Clean scoring system with even weighting (10% per check)
|
||||
- **Essential Checks Only**: Covers technical compliance, visual design, content, and marketing effectiveness
|
||||
- **No Reference Assets Required**: Works independently for quick analysis
|
||||
- **Brand-Specific Optimization**: Maintained Unilever and Diageo profiles with specialized scoring logic
|
||||
- **Profile Cleanup**: Removed redundant "All Checks", "General Key Visual", and "General Packaging" profiles
|
||||
|
||||
#### **Fixed Scoring System** 🧮
|
||||
- **Corrected 100-Point Scale**: Fixed calculation bug where General Check profile showed 490/100 instead of correct scores
|
||||
- **Multi-Scale Support**: System now handles different profile weight structures correctly
|
||||
- General Check (10.0 total weight) → Direct scoring for 100-point scale
|
||||
- Other profiles (1.0-1.2 total weight) → Scaled scoring for traditional systems
|
||||
- **Enhanced JSON Merging**: Improved extraction of multiple JSON blocks from LLM responses
|
||||
- Combines metadata (face_present, new_present) with scoring data
|
||||
- Enables proper bonus check logic for brand profiles
|
||||
|
||||
### **December 2024 - Authentication & UX Enhancements** 🚀
|
||||
|
||||
#### **Enhanced Profile-Specific Scoring** 📊
|
||||
- **Unilever Key Visual Profile**: Implemented stringent zero-score logic for critical elements
|
||||
|
|
@ -188,17 +208,51 @@ When you start an analysis, the system performs these streamlined steps:
|
|||
|
||||
## 🎯 Available QC Profiles
|
||||
|
||||
### Brand-Specific Profiles
|
||||
- **Diageo Key Visual**: Optimized for Diageo brand guidelines and key visual requirements
|
||||
- **Diageo Packaging**: Tailored for Diageo packaging design requirements
|
||||
- **Unilever Key Visual**: Focused on Unilever brand standards and visual hierarchy
|
||||
- **Unilever Packaging**: Specialized for Unilever packaging compliance
|
||||
The system includes 6 focused QC profiles designed for different use cases:
|
||||
|
||||
### General Profiles
|
||||
- **All Checks**: Comprehensive analysis using all available QC checks
|
||||
- **General Key Visual**: Standard checks for key visual/hero image analysis
|
||||
- **General Packaging**: Technical checks for packaging design compliance
|
||||
- **Inclusive Accessibility**: Focuses on accessibility and inclusive design practices
|
||||
### **1. General Check** (10 checks, 100-point scale) 🎯
|
||||
- **Purpose**: Streamlined general-purpose QC analysis
|
||||
- **Checks**: aspect_ratio, background_contrast, call_to_action, curved_edges_digital, curved_edges_print, element_alignment, product_visibility, safety_area, text_readability, visual_elements_count
|
||||
- **Weighting**: Even distribution (10% each)
|
||||
- **Requirements**: No reference assets needed
|
||||
- **Best For**: Quick comprehensive analysis of any visual content
|
||||
|
||||
### **Brand-Specific Profiles** 🏢
|
||||
|
||||
#### **2. Unilever Key Visual** (15 checks, 120-point scale)
|
||||
- **Purpose**: Unilever brand guidelines for key visual materials
|
||||
- **Special Logic**: Bonus checks with zero-scoring for missing elements (face_visibility, new_visibility, face_gaze_direction)
|
||||
- **Requirements**: Brand guidelines recommended
|
||||
- **Best For**: Unilever marketing materials and key visuals
|
||||
|
||||
#### **3. Unilever Packaging** (17 checks)
|
||||
- **Purpose**: Unilever packaging design standards
|
||||
- **Requirements**: Brand guidelines recommended
|
||||
- **Best For**: Unilever product packaging designs
|
||||
|
||||
#### **4. Diageo Key Visual** (11 checks)
|
||||
- **Purpose**: Diageo brand guidelines for key visuals
|
||||
- **Requirements**: Brand guidelines recommended
|
||||
- **Best For**: Diageo advertising and marketing materials
|
||||
|
||||
#### **5. Diageo Packaging** (13 checks)
|
||||
- **Purpose**: Diageo packaging design standards
|
||||
- **Requirements**: Brand guidelines recommended
|
||||
- **Best For**: Diageo product packaging and labeling
|
||||
|
||||
### **Specialized Profiles** ♿
|
||||
|
||||
#### **6. Inclusive Accessibility** (2 checks)
|
||||
- **Purpose**: Focused accessibility compliance
|
||||
- **Checks**: accessibility, inclusive design
|
||||
- **Requirements**: No reference assets needed
|
||||
- **Best For**: Accessibility audits and inclusive design validation
|
||||
|
||||
### **Profile Selection Guidelines**
|
||||
- **🎯 General content analysis**: Use General Check
|
||||
- **🏢 Brand-specific analysis**: Use appropriate brand profile (Unilever/Diageo)
|
||||
- **♿ Accessibility focus**: Use Inclusive Accessibility
|
||||
- **🔄 Mixed requirements**: Profiles can be combined in multi-profile analysis
|
||||
|
||||
### 🎨 Consumer-Focused Analysis
|
||||
|
||||
|
|
@ -250,7 +304,7 @@ The system now uses **batch-based parallel processing** to dramatically improve
|
|||
|
||||
## 🔍 Quality Control Checks
|
||||
|
||||
The system includes 34+ specialized QC checks organized into categories:
|
||||
The system includes 33 specialized QC checks organized into categories:
|
||||
|
||||
### Visual Design Checks
|
||||
- **Logo Visibility**: Ensures brand logo is clearly visible and prominent
|
||||
|
|
|
|||
|
|
@ -80,11 +80,14 @@ def extract_json_from_response(response_text):
|
|||
except Exception as e:
|
||||
print(f"Could not parse JSON block: {e}")
|
||||
|
||||
# If we found multiple JSON blocks, use the last one that's not empty
|
||||
# If we found multiple JSON blocks, merge them (later blocks override earlier blocks)
|
||||
if json_objects:
|
||||
for json_obj in reversed(json_objects):
|
||||
merged_json = {}
|
||||
for json_obj in json_objects:
|
||||
if json_obj: # If not empty
|
||||
return json_obj
|
||||
merged_json.update(json_obj)
|
||||
if merged_json:
|
||||
return merged_json
|
||||
|
||||
# If we couldn't extract JSON blocks or they were empty, look for JSON directly
|
||||
try:
|
||||
|
|
@ -206,7 +209,9 @@ def extract_score_from_result(result, profile_config=None, check_name=None):
|
|||
json_data = extract_json_from_response(result['response'])
|
||||
|
||||
# Unilever Key Visual profile specific logic
|
||||
if (profile_config and profile_config.get('name') == 'Unilever Key Visual' and
|
||||
if (profile_config and
|
||||
((hasattr(profile_config, 'name') and profile_config.name == 'Unilever Key Visual') or
|
||||
(hasattr(profile_config, 'get') and profile_config.get('name') == 'Unilever Key Visual')) and
|
||||
check_name in ['face_visibility', 'new_visibility', 'face_gaze_direction']):
|
||||
|
||||
# Check for zero score conditions based on missing elements
|
||||
|
|
@ -784,7 +789,8 @@ def generate_html_content(report_data, filename, file_path=None):
|
|||
</div>
|
||||
<div class="expandable-content" id="content-{check_name}">
|
||||
<div class="check-metadata">
|
||||
<p><strong>Weight:</strong> {weight:.3f} | <strong>Weighted Score:</strong> {weighted_score:.2f}</p>
|
||||
<p><strong>Score:</strong> {score}/10 | <strong>Weight:</strong> {weight:.1%} | <strong>Weighted Score:</strong> {weighted_score:.2f}</p>
|
||||
{'<p><strong>⭐ Bonus Check:</strong> If missing required element, this scores 0</p>' if check_name in ['face_gaze_direction', 'face_visibility', 'new_visibility'] else ''}
|
||||
<p><strong>Reference Asset:</strong> {'✅ Used' if check_name in REFERENCE_ASSET_REQUIRED_CHECKS and reference_asset_used else ('🚨 Required but missing' if check_name in REFERENCE_ASSET_REQUIRED_CHECKS else '➖ Not required')}</p>
|
||||
{f'<p><strong>Reference Asset Details:</strong> {reference_asset}</p>' if check_name in REFERENCE_ASSET_REQUIRED_CHECKS and reference_asset_used and reference_asset else ''}
|
||||
</div>
|
||||
|
|
@ -981,7 +987,8 @@ def generate_comprehensive_html_report(analysis_result, filename, file_path=None
|
|||
</div>
|
||||
<div class="expandable-content" id="content-{check_name}">
|
||||
<div class="check-metadata">
|
||||
<p><strong>Weight:</strong> {result.get('weight', 0)} | <strong>Weighted Score:</strong> {result.get('weighted_score', 0)}</p>
|
||||
<p><strong>Score:</strong> {score}/10 | <strong>Weight:</strong> {result.get('weight', 0):.1%} | <strong>Weighted Score:</strong> {result.get('weighted_score', 0):.2f}</p>
|
||||
{'<p><strong>⭐ Bonus Check:</strong> If missing required element, this scores 0</p>' if check_name in ['face_gaze_direction', 'face_visibility', 'new_visibility'] else ''}
|
||||
<p><strong>Reference Asset:</strong> {'✅ Used' if check_name in REFERENCE_ASSET_REQUIRED_CHECKS and reference_asset_used else ('🚨 Required but missing' if check_name in REFERENCE_ASSET_REQUIRED_CHECKS else '➖ Not required')}</p>
|
||||
{f'<p><strong>Reference Asset Details:</strong> {reference_asset}</p>' if check_name in REFERENCE_ASSET_REQUIRED_CHECKS and reference_asset_used and reference_asset else ''}
|
||||
</div>
|
||||
|
|
@ -1438,7 +1445,12 @@ def start_analysis():
|
|||
failed_checks += 1
|
||||
|
||||
# Calculate overall score
|
||||
overall_score = (total_weighted_score * 10) if total_weight > 0 else 0
|
||||
# For profiles with total_weight = 10.0 (like General Check), use direct weighted score
|
||||
# For profiles with total_weight = 1.0, multiply by 10 to scale to 100
|
||||
if total_weight >= 10.0:
|
||||
overall_score = total_weighted_score # Already scaled correctly
|
||||
else:
|
||||
overall_score = (total_weighted_score * 10) # Scale to 100-point system
|
||||
|
||||
# STEP 5: Prepare Combined Response
|
||||
print(f"Step 5: Preparing response")
|
||||
|
|
@ -1895,7 +1907,7 @@ def api_process_triaged_file():
|
|||
)
|
||||
|
||||
# Extract score from result
|
||||
score = extract_score_from_result(result, profile.config, check_name)
|
||||
score = extract_score_from_result(result, profile, check_name)
|
||||
result['score'] = score
|
||||
|
||||
# Process result for JSON mode
|
||||
|
|
@ -2635,7 +2647,14 @@ def api_analyze_with_triage():
|
|||
failed_checks += 1
|
||||
|
||||
# Calculate overall score - sum of weighted scores scaled to 100
|
||||
overall_score = (total_weighted_score * 10) if total_weight > 0 else 0
|
||||
# For profiles with total_weight = 10.0 (like General Check), use direct weighted score
|
||||
# For profiles with total_weight = 1.0, multiply by 10 to scale to 100
|
||||
if total_weight >= 10.0:
|
||||
overall_score = total_weighted_score # Already scaled correctly
|
||||
elif total_weight > 0:
|
||||
overall_score = (total_weighted_score * 10) # Scale to 100-point system
|
||||
else:
|
||||
overall_score = 0
|
||||
|
||||
# STEP 5: Prepare Combined Response
|
||||
print(f"Step 5: Preparing response")
|
||||
|
|
@ -3319,30 +3338,8 @@ def auth_login():
|
|||
|
||||
token = data['token']
|
||||
|
||||
# Validate and set authentication token
|
||||
success, message = auth.set_auth_token(token)
|
||||
|
||||
if success:
|
||||
# Get user information
|
||||
auth_status = auth.get_auth_status()
|
||||
response_data = {
|
||||
'success': True,
|
||||
'message': message,
|
||||
'authenticated': True,
|
||||
'user': auth_status.get('user')
|
||||
}
|
||||
|
||||
# Create response with httpOnly cookie
|
||||
response = make_response(jsonify(response_data))
|
||||
|
||||
# The cookie is already set in set_auth_token, but we need to return the response
|
||||
return response
|
||||
else:
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': message,
|
||||
'authenticated': False
|
||||
}), 401
|
||||
# Validate and set authentication token - returns response with cookie set
|
||||
return auth.set_auth_token(token)
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({
|
||||
|
|
|
|||
|
|
@ -104,10 +104,10 @@ class AuthMiddleware:
|
|||
'payload': None
|
||||
}
|
||||
|
||||
def set_auth_token(self, token: str) -> Tuple[bool, str]:
|
||||
def set_auth_token(self, token: str):
|
||||
"""
|
||||
Validate and store authentication token in httpOnly cookie.
|
||||
Returns (success, message).
|
||||
Returns Flask response with cookie set.
|
||||
"""
|
||||
try:
|
||||
# Validate token before storing
|
||||
|
|
@ -117,16 +117,21 @@ class AuthMiddleware:
|
|||
response = make_response(jsonify({
|
||||
'success': True,
|
||||
'message': 'Authentication successful',
|
||||
'authenticated': True,
|
||||
'user': self.jwt_validator.get_user_info(payload)
|
||||
}))
|
||||
|
||||
# Set httpOnly cookie with security flags
|
||||
self._set_secure_cookie(response, token, payload)
|
||||
|
||||
return True, 'Authentication token set successfully'
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
return False, f'Token validation failed: {str(e)}'
|
||||
return make_response(jsonify({
|
||||
'success': False,
|
||||
'error': f'Token validation failed: {str(e)}',
|
||||
'authenticated': False
|
||||
}), 401)
|
||||
|
||||
def clear_auth_token(self):
|
||||
"""Clear authentication cookie and return response."""
|
||||
|
|
|
|||
BIN
brand_guidelines/files/Dove_20250823_130533.pdf
Normal file
|
|
@ -16,6 +16,14 @@
|
|||
"guidelines": [
|
||||
"Hellmanns_20250805_113413"
|
||||
]
|
||||
},
|
||||
"Dove": {
|
||||
"name": "Dove",
|
||||
"created_at": "2025-08-23T13:05:33.656313",
|
||||
"file_count": 1,
|
||||
"guidelines": [
|
||||
"Dove_20250823_130533"
|
||||
]
|
||||
}
|
||||
},
|
||||
"files": {
|
||||
|
|
@ -54,8 +62,20 @@
|
|||
"tags": [],
|
||||
"upload_date": "2025-08-05T11:34:13.372342",
|
||||
"file_type": ".png"
|
||||
},
|
||||
"Dove_20250823_130533": {
|
||||
"id": "Dove_20250823_130533",
|
||||
"brand_name": "Dove",
|
||||
"original_filename": "temp_20250823_130533_- Dove Brand Book.pdf",
|
||||
"stored_filename": "Dove_20250823_130533.pdf",
|
||||
"stored_path": "brand_guidelines/files/Dove_20250823_130533.pdf",
|
||||
"file_size": 5328348,
|
||||
"description": "",
|
||||
"tags": [],
|
||||
"upload_date": "2025-08-23T13:05:33.656294",
|
||||
"file_type": ".pdf"
|
||||
}
|
||||
},
|
||||
"created_at": "2025-07-27T20:52:56.220914",
|
||||
"last_updated": "2025-08-05T11:34:13.372400"
|
||||
"last_updated": "2025-08-23T13:05:33.656319"
|
||||
}
|
||||
|
|
@ -12,3 +12,16 @@ Session 20250807_202433: analysis_mode = 'html'
|
|||
Session 20250807_203144: analysis_mode = 'html'
|
||||
Session 20250807_203255: analysis_mode = 'html'
|
||||
Session 20250807_203434: analysis_mode = 'html'
|
||||
Session 20250823_121621: analysis_mode = 'html'
|
||||
Session 20250823_124659: analysis_mode = 'html'
|
||||
Session 20250823_130057: analysis_mode = 'html'
|
||||
Session 20250823_130328: analysis_mode = 'html'
|
||||
Session 20250823_130604: analysis_mode = 'html'
|
||||
Session 20250823_131749: analysis_mode = 'html'
|
||||
Session 20250823_133626: analysis_mode = 'html'
|
||||
Session 20250823_133902: analysis_mode = 'html'
|
||||
Session 20250823_135013: analysis_mode = 'html'
|
||||
Session 20250823_142149: analysis_mode = 'html'
|
||||
Session 20250823_142644: analysis_mode = 'html'
|
||||
Session 20250823_143535: analysis_mode = 'html'
|
||||
Session 20250823_143740: analysis_mode = 'html'
|
||||
|
|
|
|||
1172
output/20250823_121621_image_(1)_2.png_report.html
Normal file
1187
output/20250823_124659_image_(1)_2.png_report.html
Normal file
1271
output/20250823_130057_image_(1)_2.png_report.html
Normal file
1175
output/20250823_130328_image_(2)_1.png_report.html
Normal file
1175
output/20250823_131749_image_1_v2.png_report.html
Normal file
|
|
@ -1,152 +0,0 @@
|
|||
{
|
||||
"name": "All Checks",
|
||||
"description": "Run all available QC checks",
|
||||
"pre_analysis_instructions": "Before assessment: Users often upload complex print production files with multiple panels, cut lines, and technical markings.\n\nYour task: Focus ONLY on the primary consumer-facing visual - what the end customer would actually see after production.\n\nKey instructions:\n• Ignore cut lines, registration marks, and production guides\n• If multiple panels exist, assess the main/largest consumer-facing design\n• Disregard technical text, color bars, or printer information\n• Focus on the final visual as it would appear on shelf/in-market\n• Treat folded/die-cut layouts as the assembled final product\n\nSTEPS TO EVALUATE:\n1. Examine the design components (logos, pack shots, icons, images, text blocks, promotion badges, etc.). Each distinct object or text grouping counts as one visual element that the viewer must actively notice.\n2. Count the total number of these distinct visual elements.\n3. If the count is more than 4, the design fails this checkpoint, as it may be too cluttered or complex.",
|
||||
"checks": {
|
||||
"logo_visibility": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"brand_assets_visibility": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"visual_elements_count": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"background_contrast": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"face_visibility": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"new_visibility": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"visual_hierarchy": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"supporting_images": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"curved_edges": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"visuals_left_text_right": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"face_gaze_direction": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"lowercase_text": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"call_to_action": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"word_count": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"imperative_verb": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"file_naming": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"layer_organization": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"color_format": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"image_resolution": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"safety_area": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"element_alignment": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"animation_transitions": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"responsiveness": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"dark_mode_legibility": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"print_bleed": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"crop_marks": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"text_readability": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"product_visibility": {
|
||||
"weight": 0.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
67
profiles/general_check.json
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"name": "General Check",
|
||||
"description": "Streamlined QC profile with 10 essential checks that don't require reference assets - Even weighting with 100-point total, each tool scores out of 10",
|
||||
"pre_analysis_instructions": "This is a focused quality control analysis that evaluates the most essential design and content criteria without requiring reference assets. Each check is equally weighted (10% each) to provide a balanced overall assessment.\n\nFocus areas:\n• Technical compliance (aspect ratio, resolution standards)\n• Visual design (contrast, alignment, readability)\n• Content structure (visual elements count, text readability)\n• Production requirements (curved edges, safety areas)\n• Marketing effectiveness (call to action, product visibility)\n\nEach of the 10 checks contributes 10% to the final score out of 100.",
|
||||
"checks": {
|
||||
"aspect_ratio": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"background_contrast": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"call_to_action": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"curved_edges_digital": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"curved_edges_print": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"element_alignment": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"product_visibility": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"safety_area": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"text_readability": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
},
|
||||
"visual_elements_count": {
|
||||
"weight": 1.0,
|
||||
"llm": "Gemini",
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10 - 10% of total"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
{
|
||||
"name": "General Key Visual",
|
||||
"description": "General QC profile for key visual materials (single key visual, multiple key visuals on a single page, or packaging) - combines digital, print, and OOH standards",
|
||||
"pre_analysis_instructions": "Before assessment: Users often upload complex print production files with multiple panels, cut lines, and technical markings.\n\nYour task: Focus ONLY on the primary consumer-facing visual - what the end customer would actually see after production.\n\nKey instructions:\n• Ignore cut lines, registration marks, and production guides\n• If multiple panels exist, assess the main/largest consumer-facing design\n• Disregard technical text, color bars, or printer information\n• Focus on the final visual as it would appear on shelf/in-market\n• Treat folded/die-cut layouts as the assembled final product\n\nSTEPS TO EVALUATE:\n1. Examine the design components (logos, pack shots, icons, images, text blocks, promotion badges, etc.). Each distinct object or text grouping counts as one visual element that the viewer must actively notice.\n2. Count the total number of these distinct visual elements.\n3. If the count is more than 4, the design fails this checkpoint, as it may be too cluttered or complex.",
|
||||
"checks": {
|
||||
"background_contrast": {
|
||||
"weight": 0.12,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"brand_assets_visibility": {
|
||||
"weight": 0.08,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"call_to_action": {
|
||||
"weight": 0.12,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"curved_edges": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"curved_edges_digital": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"curved_edges_print": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"element_alignment": {
|
||||
"weight": 0.06,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"face_gaze_direction": {
|
||||
"weight": 0.04,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"face_visibility": {
|
||||
"weight": 0.08,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"imperative_verb": {
|
||||
"weight": 0.08,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"logo_visibility": {
|
||||
"weight": 0.12,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"lowercase_text": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"new_visibility": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"product_visibility": {
|
||||
"weight": 0.04,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"supporting_images": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"text_readability": {
|
||||
"weight": 0.12,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"visual_elements_count": {
|
||||
"weight": 0.08,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"visual_hierarchy": {
|
||||
"weight": 0.12,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"visuals_left_text_right": {
|
||||
"weight": 0.06,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"word_count": {
|
||||
"weight": 0.06,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"responsiveness": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"dark_mode_legibility": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"file_naming": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"print_bleed": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"crop_marks": {
|
||||
"weight": 0.02,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
{
|
||||
"name": "General Packaging",
|
||||
"description": "General QC profile for packaging materials (product packaging, labels, POS displays, gift cards)",
|
||||
"pre_analysis_instructions": "Before assessment: Users often upload complex print production files with multiple panels, cut lines, and technical markings.\n\nYour task: Focus ONLY on the primary consumer-facing visual - what the end customer would actually see after production.\n\nKey instructions:\n• Ignore cut lines, registration marks, and production guides\n• If multiple panels exist, assess the main/largest consumer-facing design\n• Disregard technical text, color bars, or printer information\n• Focus on the final visual as it would appear on shelf/in-market\n• Treat folded/die-cut layouts as the assembled final product\n\nSTEPS TO EVALUATE:\n1. Examine the design components (logos, pack shots, icons, images, text blocks, promotion badges, etc.). Each distinct object or text grouping counts as one visual element that the viewer must actively notice.\n2. Count the total number of these distinct visual elements.\n3. If the count is more than 4, the design fails this checkpoint, as it may be too cluttered or complex.",
|
||||
"checks": {
|
||||
"background_contrast": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"brand_assets_visibility": {
|
||||
"weight": 0.15,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"call_to_action": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"curved_edges": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"face_gaze_direction": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"face_visibility": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"logo_visibility": {
|
||||
"weight": 0.15,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"lowercase_text": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"new_visibility": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"product_visibility": {
|
||||
"weight": 0.15,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"visual_elements_count": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"text_readability": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
},
|
||||
"color_format": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,77 +6,98 @@
|
|||
"background_contrast": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"brand_assets_visibility": {
|
||||
"weight": 0.12,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"call_to_action": {
|
||||
"weight": 0.03,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"curved_edges": {
|
||||
"weight": 0.04,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"face_gaze_direction": {
|
||||
"weight": 0.06,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Bonus check - Individual score out of 10",
|
||||
"additional_notes": "If there is no face then score this a 0",
|
||||
"bonus_check": true
|
||||
},
|
||||
"face_visibility": {
|
||||
"weight": 0.07,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Bonus check - Individual score out of 10",
|
||||
"additional_notes": "If there is no face then score this a 0",
|
||||
"bonus_check": true
|
||||
},
|
||||
"imperative_verb": {
|
||||
"weight": 0.02,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"logo_visibility": {
|
||||
"weight": 0.14,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"lowercase_text": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"new_visibility": {
|
||||
"weight": 0.07,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Bonus check - Individual score out of 10",
|
||||
"additional_notes": "If there is no New text visible then score this a 0",
|
||||
"bonus_check": true
|
||||
},
|
||||
"supporting_images": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"visual_elements_count": {
|
||||
"weight": 0.14,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"visual_hierarchy": {
|
||||
"weight": 0.10,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"visuals_left_text_right": {
|
||||
"weight": 0.06,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
},
|
||||
"word_count": {
|
||||
"weight": 0.05,
|
||||
"llm": "Gemini",
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"notes": "Individual score out of 10"
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
uploads/20250823_121621/image (1) 2.png
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
BIN
uploads/20250823_124659/image (1) 2.png
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
BIN
uploads/20250823_130057/image (1) 2.png
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
BIN
uploads/20250823_130328/image (2) 1.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
uploads/20250823_130604/Screenshot 2025-08-21 at 15.39.06.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
uploads/20250823_131749/image 1_v2.png
Normal file
|
After Width: | Height: | Size: 187 KiB |
BIN
uploads/20250823_133626/image (3).png
Normal file
|
After Width: | Height: | Size: 234 KiB |
BIN
uploads/20250823_133902/11729 Gordons BTL - GB LDG KVs.jpg
Normal file
|
After Width: | Height: | Size: 848 KiB |
BIN
uploads/20250823_135013/11729 Gordons BTL - GB LDG KVs.jpg
Normal file
|
After Width: | Height: | Size: 848 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
BIN
uploads/20250823_143535/12135 Malts Portfolio KV Pt 420x594.jpg
Normal file
|
After Width: | Height: | Size: 825 KiB |
BIN
uploads/20250823_143740/12135 Malts Portfolio KV Pt 420x594.jpg
Normal file
|
After Width: | Height: | Size: 825 KiB |
39
web_ui.html
|
|
@ -670,7 +670,9 @@
|
|||
console.log('Current URL:', window.location.href);
|
||||
console.log(`Attempting to fetch: ${BASE_PATH}api/profiles`);
|
||||
|
||||
const response = await fetch(`${BASE_PATH}api/profiles`);
|
||||
const response = await fetch(`${BASE_PATH}api/profiles`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
console.log('Response received:', response);
|
||||
console.log('Response status:', response.status);
|
||||
console.log('Response ok:', response.ok);
|
||||
|
|
@ -753,7 +755,9 @@
|
|||
async function loadSavedFiles(retryAttempts = 0, maxRetries = 3) {
|
||||
try {
|
||||
console.log(`Loading saved files... (attempt ${retryAttempts + 1}/${maxRetries + 1})`);
|
||||
const response = await fetch(`${BASE_PATH}api/output_files`);
|
||||
const response = await fetch(`${BASE_PATH}api/output_files`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (data.files && data.files.length > 0) {
|
||||
|
|
@ -787,7 +791,9 @@
|
|||
// Store the current number of files for comparison
|
||||
let previousFileCount = 0;
|
||||
try {
|
||||
const response = await fetch(`${BASE_PATH}api/output_files`);
|
||||
const response = await fetch(`${BASE_PATH}api/output_files`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await response.json();
|
||||
previousFileCount = data.files ? data.files.length : 0;
|
||||
console.log(`Current file count: ${previousFileCount}`);
|
||||
|
|
@ -803,7 +809,9 @@
|
|||
|
||||
try {
|
||||
console.log(`Refresh attempt ${i + 1} after ${refreshAttempts[i]}ms delay`);
|
||||
const response = await fetch(`${BASE_PATH}api/output_files`);
|
||||
const response = await fetch(`${BASE_PATH}api/output_files`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (data.files && data.files.length > 0) {
|
||||
|
|
@ -1165,7 +1173,8 @@
|
|||
|
||||
const response = await fetch(`${BASE_PATH}api/start_analysis`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
body: formData,
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
console.log('Analysis response status:', response.status);
|
||||
|
|
@ -1227,7 +1236,9 @@
|
|||
const pollProgress = async () => {
|
||||
try {
|
||||
console.log(`Polling progress for session: ${sessionId}`);
|
||||
const response = await fetch(`${BASE_PATH}api/progress/${sessionId}`);
|
||||
const response = await fetch(`${BASE_PATH}api/progress/${sessionId}`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
console.log('Progress API response status:', response.status);
|
||||
if (!response.ok) {
|
||||
console.error(`Progress check failed with status: ${response.status}`);
|
||||
|
|
@ -1712,8 +1723,8 @@
|
|||
try {
|
||||
// Load profiles and QC apps in parallel
|
||||
const [profilesResponse, qcAppsResponse] = await Promise.all([
|
||||
fetch(`${BASE_PATH}api/profiles`),
|
||||
fetch(`${BASE_PATH}api/qc-apps`)
|
||||
fetch(`${BASE_PATH}api/profiles`, { credentials: 'include' }),
|
||||
fetch(`${BASE_PATH}api/qc-apps`, { credentials: 'include' })
|
||||
]);
|
||||
|
||||
if (!profilesResponse.ok || !qcAppsResponse.ok) {
|
||||
|
|
@ -1964,7 +1975,8 @@
|
|||
|
||||
try {
|
||||
const response = await fetch(`${BASE_PATH}api/profiles/${selectedProfileId}`, {
|
||||
method: 'DELETE'
|
||||
method: 'DELETE',
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -2014,6 +2026,7 @@
|
|||
|
||||
fetch(`${BASE_PATH}api/brand_guidelines`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
|
|
@ -2049,7 +2062,9 @@
|
|||
// Load brand guidelines for settings modal
|
||||
async function loadSettingsBrandGuidelines() {
|
||||
try {
|
||||
const response = await fetch(`${BASE_PATH}api/brand_guidelines`);
|
||||
const response = await fetch(`${BASE_PATH}api/brand_guidelines`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await response.json();
|
||||
console.log('Settings brand guidelines loaded:', data);
|
||||
|
||||
|
|
@ -2105,7 +2120,9 @@
|
|||
if (!referenceAssetSelect) return;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${BASE_PATH}api/brand_guidelines`);
|
||||
const response = await fetch(`${BASE_PATH}api/brand_guidelines`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
referenceAssetSelect.innerHTML = '<option value="">No reference asset selected</option>';
|
||||
|
|
|
|||