// noqa: js-006 - async init pattern is safe, loadData has try/catch /** * Code Quality Violations List Component * Manages the violations list page with filtering and pagination */ // ✅ Use centralized logger const codeQualityViolationsLog = window.LogConfig.createLogger('CODE-QUALITY'); function codeQualityViolations() { return { // Extend base data ...data(), // Set current page for navigation currentPage: 'code-quality', // Violations-specific data loading: false, error: null, violations: [], pagination: { page: 1, per_page: 20, total: 0, pages: 0 }, filters: { validator_type: '', severity: '', status: '', rule_id: '', file_path: '' }, async init() { // Guard against multiple initialization if (window._codeQualityViolationsInitialized) { codeQualityViolationsLog.warn('Already initialized, skipping'); return; } window._codeQualityViolationsInitialized = true; // Load platform settings for rows per page if (window.PlatformSettings) { this.pagination.per_page = await window.PlatformSettings.getRowsPerPage(); } // Load filters from URL params const params = new URLSearchParams(window.location.search); this.filters.validator_type = params.get('validator_type') || ''; this.filters.severity = params.get('severity') || ''; this.filters.status = params.get('status') || ''; this.filters.rule_id = params.get('rule_id') || ''; this.filters.file_path = params.get('file_path') || ''; await this.loadViolations(); }, async loadViolations() { this.loading = true; this.error = null; try { // Build query params const params = { page: this.pagination.page.toString(), page_size: this.pagination.per_page.toString() }; if (this.filters.validator_type) params.validator_type = this.filters.validator_type; if (this.filters.severity) params.severity = this.filters.severity; if (this.filters.status) params.status = this.filters.status; if (this.filters.rule_id) params.rule_id = this.filters.rule_id; if (this.filters.file_path) params.file_path = this.filters.file_path; const data = await apiClient.get('/admin/code-quality/violations', params); this.violations = data.violations; this.pagination.total = data.total; this.pagination.pages = data.total_pages; // Update URL with current filters (without reloading) this.updateURL(); } catch (err) { codeQualityViolationsLog.error('Failed to load violations:', err); this.error = err.message; // Redirect to login if unauthorized if (err.message.includes('Unauthorized')) { window.location.href = '/admin/login'; } } finally { this.loading = false; } }, applyFilters() { // Reset to page 1 when filters change this.pagination.page = 1; this.loadViolations(); }, async nextPage() { if (this.pagination.page < this.pagination.pages) { this.pagination.page++; await this.loadViolations(); } }, // Computed: Total number of pages get totalPages() { return this.pagination.pages; }, // Computed: Start index for pagination display get startIndex() { if (this.pagination.total === 0) return 0; return (this.pagination.page - 1) * this.pagination.per_page + 1; }, // Computed: End index for pagination display get endIndex() { const end = this.pagination.page * this.pagination.per_page; return end > this.pagination.total ? this.pagination.total : end; }, // Computed: Generate page numbers array with ellipsis get pageNumbers() { const pages = []; const totalPages = this.totalPages; const current = this.pagination.page; if (totalPages <= 7) { // Show all pages if 7 or fewer for (let i = 1; i <= totalPages; i++) { pages.push(i); } } else { // Always show first page pages.push(1); if (current > 3) { pages.push('...'); } // Show pages around current page const start = Math.max(2, current - 1); const end = Math.min(totalPages - 1, current + 1); for (let i = start; i <= end; i++) { pages.push(i); } if (current < totalPages - 2) { pages.push('...'); } // Always show last page pages.push(totalPages); } return pages; }, async previousPage() { if (this.pagination.page > 1) { this.pagination.page--; await this.loadViolations(); } }, goToPage(pageNum) { if (pageNum !== '...' && pageNum >= 1 && pageNum <= this.totalPages) { this.pagination.page = pageNum; this.loadViolations(); } }, updateURL() { const params = new URLSearchParams(); if (this.filters.validator_type) params.set('validator_type', this.filters.validator_type); if (this.filters.severity) params.set('severity', this.filters.severity); if (this.filters.status) params.set('status', this.filters.status); if (this.filters.rule_id) params.set('rule_id', this.filters.rule_id); if (this.filters.file_path) params.set('file_path', this.filters.file_path); const newURL = params.toString() ? `${window.location.pathname}?${params.toString()}` : window.location.pathname; window.history.replaceState({}, '', newURL); } }; }