29154bd651
Co-authored-by: Copilot <copilot@github.com>
337 lines
10 KiB
Markdown
337 lines
10 KiB
Markdown
# Directory Structure Helper - Canvas API
|
|
|
|
## Quick Directory Setup Scripts
|
|
|
|
### Windows PowerShell Script
|
|
Save as `create-canvas-structure.ps1`:
|
|
|
|
```powershell
|
|
# Create Canvas API directory structure
|
|
# Run from: app/static/images/
|
|
|
|
param(
|
|
[string]$BaseType = "doors",
|
|
[string]$SubType = "storm",
|
|
[string]$ProductCode = ""
|
|
)
|
|
|
|
# Create base structure
|
|
$basePath = "."
|
|
|
|
# Create type/subtype/layers directories
|
|
New-Item -ItemType Directory -Force -Path "$basePath/$BaseType/$SubType/layers" | Out-Null
|
|
Write-Host "✓ Created: $BaseType/$SubType/layers/"
|
|
|
|
# Create product-specific directory if provided
|
|
if ($ProductCode) {
|
|
New-Item -ItemType Directory -Force -Path "$basePath/$BaseType/$SubType/$ProductCode" | Out-Null
|
|
Write-Host "✓ Created: $BaseType/$SubType/$ProductCode/"
|
|
}
|
|
|
|
# Create type-level layers directory
|
|
New-Item -ItemType Directory -Force -Path "$basePath/$BaseType/layers" | Out-Null
|
|
Write-Host "✓ Created: $BaseType/layers/"
|
|
|
|
# Create global layers directory
|
|
New-Item -ItemType Directory -Force -Path "$basePath/layers" | Out-Null
|
|
Write-Host "✓ Created: layers/"
|
|
|
|
Write-Host "`nDirectory structure created successfully!"
|
|
Write-Host "Now add your images to the appropriate directories."
|
|
```
|
|
|
|
**Usage:**
|
|
```powershell
|
|
# From app/static/images/ directory
|
|
.\create-canvas-structure.ps1 -BaseType "doors" -SubType "storm" -ProductCode "404"
|
|
.\create-canvas-structure.ps1 -BaseType "windows" -SubType "double-hung" -ProductCode "505"
|
|
```
|
|
|
|
### Linux/Mac Bash Script
|
|
Save as `create-canvas-structure.sh`:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Create Canvas API directory structure
|
|
# Run from: app/static/images/
|
|
|
|
BASE_TYPE=${1:-"doors"}
|
|
SUB_TYPE=${2:-"storm"}
|
|
PRODUCT_CODE=$3
|
|
|
|
# Create type/subtype/layers directories
|
|
mkdir -p "$BASE_TYPE/$SUB_TYPE/layers"
|
|
echo "✓ Created: $BASE_TYPE/$SUB_TYPE/layers/"
|
|
|
|
# Create product-specific directory if provided
|
|
if [ -n "$PRODUCT_CODE" ]; then
|
|
mkdir -p "$BASE_TYPE/$SUB_TYPE/$PRODUCT_CODE"
|
|
echo "✓ Created: $BASE_TYPE/$SUB_TYPE/$PRODUCT_CODE/"
|
|
fi
|
|
|
|
# Create type-level layers directory
|
|
mkdir -p "$BASE_TYPE/layers"
|
|
echo "✓ Created: $BASE_TYPE/layers/"
|
|
|
|
# Create global layers directory
|
|
mkdir -p "layers"
|
|
echo "✓ Created: layers/"
|
|
|
|
echo ""
|
|
echo "Directory structure created successfully!"
|
|
echo "Now add your images to the appropriate directories."
|
|
```
|
|
|
|
**Usage:**
|
|
```bash
|
|
# From app/static/images/ directory
|
|
chmod +x create-canvas-structure.sh
|
|
./create-canvas-structure.sh doors storm 404
|
|
./create-canvas-structure.sh windows double-hung 505
|
|
```
|
|
|
|
## Python Script for Bulk Setup
|
|
Save as `setup_canvas_structure.py` in `app/`:
|
|
|
|
```python
|
|
"""
|
|
Setup Canvas API directory structure for multiple products
|
|
"""
|
|
import os
|
|
import json
|
|
|
|
def load_products():
|
|
"""Load products from products.json"""
|
|
with open('data/products.json', 'r', encoding='utf-8') as f:
|
|
return json.load(f)
|
|
|
|
def create_canvas_directories():
|
|
"""Create directory structure based on product data"""
|
|
products = load_products()
|
|
base_path = 'static/images'
|
|
|
|
created_dirs = set()
|
|
|
|
for product in products:
|
|
# Get product type info
|
|
base_type = product.get('baseType', '').lower()
|
|
subtype_obj = product.get('subType', {})
|
|
product_code = product.get('productCode') or product.get('id')
|
|
|
|
if not base_type or not product_code:
|
|
continue
|
|
|
|
# Extract subtype
|
|
sub_type = None
|
|
if isinstance(subtype_obj, dict):
|
|
if subtype_obj.get('door'):
|
|
sub_type = subtype_obj['door'].lower().replace(' ', '-')
|
|
elif subtype_obj.get('window'):
|
|
sub_type = subtype_obj['window'].lower().replace(' ', '-')
|
|
|
|
if not sub_type:
|
|
continue
|
|
|
|
# Create directories
|
|
dirs_to_create = [
|
|
f"{base_path}/{base_type}/{sub_type}/layers",
|
|
f"{base_path}/{base_type}/{sub_type}/{product_code}",
|
|
f"{base_path}/{base_type}/layers",
|
|
f"{base_path}/layers"
|
|
]
|
|
|
|
for dir_path in dirs_to_create:
|
|
if dir_path not in created_dirs:
|
|
os.makedirs(dir_path, exist_ok=True)
|
|
created_dirs.add(dir_path)
|
|
print(f"✓ Created: {dir_path}")
|
|
|
|
print(f"\n✅ Created {len(created_dirs)} directories")
|
|
print("\nNext steps:")
|
|
print("1. Move your product images to the appropriate directories")
|
|
print("2. Add 'useCanvasAPI': true to product imageConfig")
|
|
print("3. Test with: /api/canvas/<product_code>/info")
|
|
|
|
if __name__ == '__main__':
|
|
create_canvas_directories()
|
|
```
|
|
|
|
**Usage:**
|
|
```bash
|
|
cd app/
|
|
python setup_canvas_structure.py
|
|
```
|
|
|
|
## Manual Directory Creation Reference
|
|
|
|
### Complete Structure Example
|
|
```
|
|
app/static/images/
|
|
├── doors/
|
|
│ ├── storm/
|
|
│ │ ├── 404/
|
|
│ │ │ ├── base.jpg
|
|
│ │ │ ├── door-white.png
|
|
│ │ │ └── door-black.png
|
|
│ │ ├── 505/
|
|
│ │ │ ├── base.jpg
|
|
│ │ │ └── door-white.png
|
|
│ │ └── layers/
|
|
│ │ ├── base.jpg
|
|
│ │ ├── hardware.png
|
|
│ │ └── foreground.png
|
|
│ ├── entry/
|
|
│ │ ├── 600/
|
|
│ │ │ ├── base.jpg
|
|
│ │ │ └── door-bronze.png
|
|
│ │ └── layers/
|
|
│ │ └── foreground-plants.png
|
|
│ └── layers/
|
|
│ └── hardware-generic.png
|
|
├── windows/
|
|
│ ├── storm/
|
|
│ │ ├── 450/
|
|
│ │ │ └── base.jpg
|
|
│ │ └── layers/
|
|
│ │ └── foreground-minimal.png
|
|
│ └── layers/
|
|
│ └── base-generic.jpg
|
|
└── layers/
|
|
├── foreground-default.png
|
|
└── base-generic.jpg
|
|
```
|
|
|
|
## File Naming Conventions
|
|
|
|
### Layer Files
|
|
- **Base**: `base.jpg` or `base.png`
|
|
- **Door (no color)**: `door.png`
|
|
- **Door (with color)**: `door-white.png`, `door-black.png`, `door-bronze.png`
|
|
- **Hardware**: `hardware.png`
|
|
- **Foreground**: `foreground.png` or descriptive like `foreground-plants.png`
|
|
- **Overlay**: `overlay.png` or `view-inside.png`, `view-outside.png`
|
|
|
|
### Tips
|
|
- Use lowercase for color names in filenames
|
|
- Use hyphens to separate words
|
|
- Be descriptive for shared files: `foreground-spring-plants.png`
|
|
- Keep product-specific files simple: `base.jpg`, `door-white.png`
|
|
|
|
## Migration Helper
|
|
|
|
### Identify Duplicate Files
|
|
```powershell
|
|
# Windows PowerShell
|
|
Get-ChildItem -Path "app/static/images/products" -Recurse -File |
|
|
Group-Object -Property Length, Name |
|
|
Where-Object { $_.Count -gt 1 } |
|
|
Select-Object Name, Count
|
|
```
|
|
|
|
```bash
|
|
# Linux/Mac
|
|
find app/static/images/products -type f -exec md5sum {} + |
|
|
sort |
|
|
awk 'BEGIN{cmd="md5sum"}{if($1==prev){print $2}else{prev=$1}}'
|
|
```
|
|
|
|
This will show you which files are duplicated and can be shared.
|
|
|
|
## Validation Script
|
|
|
|
Save as `validate_canvas_structure.py`:
|
|
|
|
```python
|
|
"""
|
|
Validate Canvas API directory structure
|
|
"""
|
|
import os
|
|
import json
|
|
|
|
def validate_structure():
|
|
"""Check if directory structure matches product data"""
|
|
with open('app/data/products.json', 'r', encoding='utf-8') as f:
|
|
products = json.load(f)
|
|
|
|
issues = []
|
|
base_path = 'app/static/images'
|
|
|
|
for product in products:
|
|
if not product.get('imageConfig', {}).get('useCanvasAPI'):
|
|
continue
|
|
|
|
product_code = product.get('productCode') or product.get('id')
|
|
base_type = product.get('baseType', '').lower()
|
|
subtype_obj = product.get('subType', {})
|
|
|
|
# Extract subtype
|
|
sub_type = None
|
|
if isinstance(subtype_obj, dict):
|
|
if subtype_obj.get('door'):
|
|
sub_type = subtype_obj['door'].lower().replace(' ', '-')
|
|
elif subtype_obj.get('window'):
|
|
sub_type = subtype_obj['window'].lower().replace(' ', '-')
|
|
|
|
if not all([product_code, base_type, sub_type]):
|
|
issues.append(f"⚠️ {product_code}: Missing type/subtype info")
|
|
continue
|
|
|
|
# Check if product directory exists
|
|
product_dir = f"{base_path}/{base_type}/{sub_type}/{product_code}"
|
|
if not os.path.exists(product_dir):
|
|
issues.append(f"❌ {product_code}: Directory not found: {product_dir}")
|
|
else:
|
|
# Check for at least one image file
|
|
files = os.listdir(product_dir)
|
|
image_files = [f for f in files if f.endswith(('.png', '.jpg', '.jpeg', '.webp'))]
|
|
if not image_files:
|
|
issues.append(f"⚠️ {product_code}: No images in {product_dir}")
|
|
else:
|
|
print(f"✓ {product_code}: {len(image_files)} images found")
|
|
|
|
if issues:
|
|
print("\n❌ Issues found:")
|
|
for issue in issues:
|
|
print(f" {issue}")
|
|
else:
|
|
print("\n✅ All Canvas API products validated successfully!")
|
|
|
|
if __name__ == '__main__':
|
|
validate_structure()
|
|
```
|
|
|
|
**Usage:**
|
|
```bash
|
|
python validate_canvas_structure.py
|
|
```
|
|
|
|
## Quick Commands
|
|
|
|
### Create structure for all common types
|
|
```bash
|
|
# Doors
|
|
mkdir -p app/static/images/doors/{storm,entry,patio,screen}/layers
|
|
mkdir -p app/static/images/doors/layers
|
|
|
|
# Windows
|
|
mkdir -p app/static/images/windows/{storm,double-hung,casement,sliding}/layers
|
|
mkdir -p app/static/images/windows/layers
|
|
|
|
# Global
|
|
mkdir -p app/static/images/layers
|
|
```
|
|
|
|
### Move images from old structure
|
|
```bash
|
|
# Example: Move shared hardware from products to shared layers
|
|
mv app/static/images/products/*/hardware.png app/static/images/doors/storm/layers/
|
|
```
|
|
|
|
## Conclusion
|
|
|
|
These scripts help you quickly set up and validate the Canvas API directory structure. Choose the approach that works best for your workflow:
|
|
|
|
- **Manual**: Create directories as needed
|
|
- **Scripts**: Automate creation for multiple products
|
|
- **Migration**: Use helper scripts to identify duplicates and reorganize
|