@@ -0,0 +1,336 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user