feat: add PlatformSettings for pagination and vendor filter improvements
Platform Settings: - Add PlatformSettings utility in init-alpine.js with 5-min cache - Add Display tab in /admin/settings for rows_per_page config - Integrate PlatformSettings.getRowsPerPage() in all paginated pages - Standardize default per_page to 20 across all admin pages - Add documentation at docs/frontend/shared/platform-settings.md Architecture Rules: - Add JS-010: enforce PlatformSettings usage for pagination - Add JS-011: enforce standard pagination structure - Add JS-012: detect double /api/v1 prefix in apiClient calls - Implement all rules in validate_architecture.py Vendor Filter (Tom Select): - Add vendor filter to marketplace-products, vendor-products, customers, inventory, and vendor-themes pages - Add selectedVendor display panel with clear button - Add localStorage persistence for vendor selection - Fix double /api/v1 prefix in vendor-selector.js Bug Fixes: - Remove duplicate PlatformSettings from utils.js - Fix customers.js pagination structure (page_size → per_page) - Fix code-quality-violations.js pagination structure 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2698,6 +2698,138 @@ class ArchitectureValidator:
|
||||
# JS-004: Check Alpine components set currentPage
|
||||
self._check_alpine_current_page(file_path, content, lines)
|
||||
|
||||
# JS-010: Check PlatformSettings usage for pagination
|
||||
self._check_platform_settings_usage(file_path, content, lines)
|
||||
|
||||
# JS-011: Check standard pagination structure
|
||||
self._check_pagination_structure(file_path, content, lines)
|
||||
|
||||
# JS-012: Check for double /api/v1 prefix in API calls
|
||||
self._check_api_prefix_usage(file_path, content, lines)
|
||||
|
||||
def _check_platform_settings_usage(
|
||||
self, file_path: Path, content: str, lines: list[str]
|
||||
):
|
||||
"""
|
||||
JS-010: Check that pages with pagination use PlatformSettings.getRowsPerPage()
|
||||
"""
|
||||
# Skip excluded files
|
||||
excluded_files = ["init-alpine.js", "init-api-client.js", "settings.js"]
|
||||
if file_path.name in excluded_files:
|
||||
return
|
||||
|
||||
# Check if this file has pagination (look for pagination object)
|
||||
has_pagination = re.search(r"pagination:\s*\{", content)
|
||||
if not has_pagination:
|
||||
return
|
||||
|
||||
# Check if file uses PlatformSettings
|
||||
uses_platform_settings = "PlatformSettings" in content
|
||||
|
||||
if not uses_platform_settings:
|
||||
# Find the line where pagination is defined
|
||||
for i, line in enumerate(lines, 1):
|
||||
if "pagination:" in line and "{" in line:
|
||||
self._add_violation(
|
||||
rule_id="JS-010",
|
||||
rule_name="Use PlatformSettings for pagination",
|
||||
severity=Severity.ERROR,
|
||||
file_path=file_path,
|
||||
line_number=i,
|
||||
message="Page with pagination must use PlatformSettings.getRowsPerPage()",
|
||||
context=line.strip()[:80],
|
||||
suggestion="Add: if (window.PlatformSettings) { this.pagination.per_page = await window.PlatformSettings.getRowsPerPage(); }",
|
||||
)
|
||||
break
|
||||
|
||||
def _check_pagination_structure(
|
||||
self, file_path: Path, content: str, lines: list[str]
|
||||
):
|
||||
"""
|
||||
JS-011: Check that pagination uses standard structure (pagination.per_page not page_size)
|
||||
"""
|
||||
# Skip excluded files
|
||||
excluded_files = ["init-alpine.js"]
|
||||
if file_path.name in excluded_files:
|
||||
return
|
||||
|
||||
# Check if this file has pagination
|
||||
has_pagination = re.search(r"pagination:\s*\{", content)
|
||||
if not has_pagination:
|
||||
return
|
||||
|
||||
# Check for wrong property names in pagination object definition
|
||||
# Look for pagination object with wrong property names
|
||||
wrong_patterns = [
|
||||
(r"page_size\s*:", "page_size", "per_page"),
|
||||
(r"pageSize\s*:", "pageSize", "per_page"),
|
||||
(r"total_pages\s*:", "total_pages", "pages"),
|
||||
(r"totalPages\s*:", "totalPages (in pagination object)", "pages"),
|
||||
]
|
||||
|
||||
# Find the pagination object definition and check its properties
|
||||
in_pagination_block = False
|
||||
brace_count = 0
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
# Detect start of pagination object
|
||||
if "pagination:" in line and "{" in line:
|
||||
in_pagination_block = True
|
||||
brace_count = line.count("{") - line.count("}")
|
||||
continue
|
||||
|
||||
if in_pagination_block:
|
||||
brace_count += line.count("{") - line.count("}")
|
||||
|
||||
# Check for wrong property names only inside the pagination block
|
||||
for pattern, wrong_name, correct_name in wrong_patterns:
|
||||
if re.search(pattern, line):
|
||||
self._add_violation(
|
||||
rule_id="JS-011",
|
||||
rule_name="Use standard pagination structure",
|
||||
severity=Severity.ERROR,
|
||||
file_path=file_path,
|
||||
line_number=i,
|
||||
message=f"Use '{correct_name}' instead of '{wrong_name}' in pagination",
|
||||
context=line.strip()[:80],
|
||||
suggestion=f"Rename '{wrong_name}' to '{correct_name}'",
|
||||
)
|
||||
|
||||
# Exit pagination block when braces close
|
||||
if brace_count <= 0:
|
||||
in_pagination_block = False
|
||||
|
||||
def _check_api_prefix_usage(
|
||||
self, file_path: Path, content: str, lines: list[str]
|
||||
):
|
||||
"""
|
||||
JS-012: Check that apiClient calls don't include /api/v1 prefix
|
||||
(apiClient adds this prefix automatically)
|
||||
"""
|
||||
# Skip excluded files
|
||||
excluded_files = ["init-api-client.js", "api-client.js"]
|
||||
if file_path.name in excluded_files:
|
||||
return
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
# Skip comments
|
||||
stripped = line.strip()
|
||||
if stripped.startswith("//") or stripped.startswith("*"):
|
||||
continue
|
||||
|
||||
# Check for apiClient calls with /api/v1 prefix
|
||||
if re.search(r"apiClient\.(get|post|put|delete|patch)\s*\(\s*['\"`]/api/v1", line):
|
||||
self._add_violation(
|
||||
rule_id="JS-012",
|
||||
rule_name="Do not include /api/v1 prefix",
|
||||
severity=Severity.ERROR,
|
||||
file_path=file_path,
|
||||
line_number=i,
|
||||
message="apiClient already adds /api/v1 prefix - remove it from the endpoint",
|
||||
context=line.strip()[:80],
|
||||
suggestion="Change '/api/v1/admin/...' to '/admin/...'",
|
||||
)
|
||||
|
||||
def _validate_templates(self, target_path: Path):
|
||||
"""Validate template patterns"""
|
||||
print("📄 Validating templates...")
|
||||
|
||||
Reference in New Issue
Block a user