create_base_frontend.py 7.76 KB
#!/usr/bin/env python3
"""
Create frontend JavaScript file for base configuration.
"""

import sys
import os
import argparse
import re
from pathlib import Path

# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent))


def create_base_frontend_js(tenant_id: str, api_port: int = 6002, output_file: str = "frontend/static/js/app_base.js"):
    """
    Create frontend JavaScript file for base configuration.
    
    Args:
        tenant_id: Tenant ID
        api_port: API port
        output_file: Output file path
    """
    # Read original app.js
    original_file = Path(__file__).parent.parent / "frontend/static/js/app.js"
    if not original_file.exists():
        print(f"ERROR: Original frontend file not found: {original_file}")
        return 1
    
    with open(original_file, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # Replace API_BASE_URL
    api_url = f"http://localhost:{api_port}"
    content = content.replace(
        "const API_BASE_URL = 'http://120.76.41.98:6002';",
        f"const API_BASE_URL = '{api_url}';"
    )
    
    # Add tenant_id constant at the beginning
    content = content.replace(
        "const API_BASE_URL =",
        f"const TENANT_ID = '{tenant_id}';\nconst API_BASE_URL ="
    )
    
    # Update facets for base configuration
    base_facets = '''    const facets = [
        {
            "field": "category_keyword",
            "size": 15,
            "type": "terms"
        },
        {
            "field": "vendor_keyword",
            "size": 15,
            "type": "terms"
        },
        {
            "field": "tags_keyword",
            "size": 10,
            "type": "terms"
        },
        {
            "field": "min_price",
            "type": "range",
            "ranges": [
                {"key": "0-50", "to": 50},
                {"key": "50-100", "from": 50, "to": 100},
                {"key": "100-200", "from": 100, "to": 200},
                {"key": "200+", "from": 200}
            ]
        }
    ];'''
    
    # Find and replace facets definition (multiline match)
    facets_pattern = r'const facets = \[.*?\];'
    content = re.sub(facets_pattern, base_facets, content, flags=re.DOTALL)
    
    # Update fetch to include tenant_id header
    content = content.replace(
        "headers: {\n                'Content-Type': 'application/json',\n            },",
        f"headers: {{\n                'Content-Type': 'application/json',\n                'X-Tenant-ID': TENANT_ID,\n            }},"
    )
    
    # Replace hits with results throughout
    content = re.sub(r'\bdata\.hits\b', 'data.results', content)
    content = re.sub(r'!data\.hits', '!data.results', content)
    
    # Replace hit loop with product loop
    content = re.sub(
        r'data\.hits\.forEach\(\(hit\) => \{',
        'data.results.forEach((product) => {',
        content
    )
    
    # Remove source extraction lines
    content = re.sub(r'const source = hit\._source;\s*\n', '', content)
    content = re.sub(r'const score = hit\._custom_score \|\| hit\._score;\s*\n', 'const score = product.relevance_score;\n', content)
    
    # Replace all source. references with product.
    content = re.sub(r'\bsource\.', 'product.', content)
    
    # Replace specific field names for base configuration
    # imageUrl -> image_url
    content = re.sub(r'product\.imageUrl', 'product.image_url', content)
    # name -> title
    content = re.sub(r'product\.name', 'product.title', content)
    content = re.sub(r'product\.enSpuName', 'product.title', content)
    # categoryName -> category
    content = re.sub(r'product\.categoryName', 'product.category', content)
    # brandName -> vendor
    content = re.sub(r'product\.brandName', 'product.vendor', content)
    # price -> price (already correct)
    # Remove moq and quantity fields (not in base config)
    content = re.sub(r'<div class="product-moq">.*?</div>\s*\n', '', content, flags=re.DOTALL)
    content = re.sub(r'<div class="product-quantity">.*?</div>\s*\n', '', content, flags=re.DOTALL)
    
    # Add stock and variants display
    # Find the product-price div and add stock info after it
    stock_info = '''                <div class="product-stock">
                    ${product.in_stock ? '<span style="color: green;">In Stock</span>' : '<span style="color: red;">Out of Stock</span>'}
                    ${product.variants && product.variants.length > 0 ? `<span style="color: #666; font-size: 0.9em;">(${product.variants.length} variants)</span>` : ''}
                </div>
                
'''
    content = re.sub(
        r'(<div class="product-price">.*?</div>\s*\n)',
        r'\1' + stock_info,
        content,
        flags=re.DOTALL
    )
    
    # Update price display format
    content = re.sub(
        r'\$\{product\.price \? `\$\{product\.price\} ₽` : \'N/A\'\}',
        '${product.price ? `$${product.price.toFixed(2)}` : \'N/A\'}',
        content
    )
    
    # Add compare_at_price if exists
    content = re.sub(
        r'(\$\{product\.price \? `\$\$\{product\.price\.toFixed\(2\)\}` : \'N/A\'\})',
        r'\1${product.compare_at_price && product.compare_at_price > product.price ? `<span style="text-decoration: line-through; color: #999; font-size: 0.9em; margin-left: 8px;">$${product.compare_at_price.toFixed(2)}</span>` : \'\'}',
        content
    )
    
    # Update product-meta to use base config fields
    content = re.sub(
        r'<div class="product-meta">\s*\$\{product\.category \? escapeHtml\(product\.category\) : \'\'\}\s*\$\{product\.vendor \? \' \| \' \+ escapeHtml\(product\.vendor\) : \'\'\}\s*</div>',
        '<div class="product-meta">${product.vendor ? escapeHtml(product.vendor) : \'\'}${product.product_type ? \' | \' + escapeHtml(product.product_type) : \'\'}${product.category ? \' | \' + escapeHtml(product.category) : \'\'}</div>',
        content
    )
    
    # Remove create_time display (not in base config)
    content = re.sub(
        r'\$\{product\.create_time \? `.*?</div>\s*` : \'\'\}',
        '',
        content,
        flags=re.DOTALL
    )
    
    # Add tags display if exists
    tags_display = '''                ${product.tags ? `
                    <div class="product-tags">
                        Tags: ${escapeHtml(product.tags)}
                    </div>
                ` : ''}'''
    
    # Add tags before closing product-card div
    content = re.sub(
        r'(</div>\s*</div>\s*`;\s*\n\s*\}\);)',
        tags_display + r'\n            </div>\n        `;\n    });',
        content,
        count=1
    )
    
    # Update displayFacets for base configuration field names
    content = re.sub(
        r"facet\.field === 'categoryName_keyword'",
        "facet.field === 'category_keyword'",
        content
    )
    content = re.sub(
        r"facet\.field === 'brandName_keyword'",
        "facet.field === 'vendor_keyword'",
        content
    )
    content = re.sub(
        r"facet\.field === 'supplierName_keyword'",
        "facet.field === 'tags_keyword'",
        content
    )
    
    # Write output file
    output_path = Path(__file__).parent.parent / output_file
    output_path.parent.mkdir(parents=True, exist_ok=True)
    
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(content)
    
    print(f"Created base frontend JavaScript: {output_path}")
    return 0


def main():
    parser = argparse.ArgumentParser(description='Create frontend JavaScript for base configuration')
    parser.add_argument('--tenant-id', default='1', help='Tenant ID')
    parser.add_argument('--api-port', type=int, default=6002, help='API port')
    parser.add_argument('--output', default='frontend/static/js/app_base.js', help='Output file')
    
    args = parser.parse_args()
    
    return create_base_frontend_js(args.tenant_id, args.api_port, args.output)


if __name__ == '__main__':
    sys.exit(main())