feat: add import error tracking and translation tabs

Import Error Tracking:
- Add MarketplaceImportError model to store detailed error information
- Store row number, identifier, error type, message, and row data for each error
- Add API endpoint GET /admin/marketplace-import-jobs/{job_id}/errors
- Add UI to view and browse import errors in job details modal
- Support pagination and error type filtering

Translation Tabs:
- Replace flat translation list with tabbed interface on product detail page
- Add language tabs with full language names
- Add copy-to-clipboard functionality for translation content
- Improved UX with better visual separation of translations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-13 13:33:03 +01:00
parent 3316894c27
commit c2f42c2913
14 changed files with 542 additions and 44 deletions

View File

@@ -54,6 +54,12 @@ function adminImports() {
showJobModal: false,
selectedJob: null,
// Job errors state
jobErrors: [],
jobErrorsTotal: 0,
jobErrorsPage: 1,
loadingErrors: false,
// Auto-refresh for active jobs
autoRefreshInterval: null,
@@ -275,6 +281,58 @@ function adminImports() {
closeJobModal() {
this.showJobModal = false;
this.selectedJob = null;
// Clear errors state
this.jobErrors = [];
this.jobErrorsTotal = 0;
this.jobErrorsPage = 1;
},
/**
* Load errors for a specific job
*/
async loadJobErrors(jobId) {
if (!jobId) return;
this.loadingErrors = true;
this.jobErrorsPage = 1;
try {
const response = await apiClient.get(
`/admin/marketplace-import-jobs/${jobId}/errors?page=1&limit=20`
);
this.jobErrors = response.errors || [];
this.jobErrorsTotal = response.total || 0;
adminImportsLog.debug('Loaded job errors:', this.jobErrors.length);
} catch (error) {
adminImportsLog.error('Failed to load job errors:', error);
this.error = error.message || 'Failed to load import errors';
} finally {
this.loadingErrors = false;
}
},
/**
* Load more errors (pagination)
*/
async loadMoreJobErrors(jobId) {
if (!jobId || this.loadingErrors) return;
this.loadingErrors = true;
this.jobErrorsPage++;
try {
const response = await apiClient.get(
`/admin/marketplace-import-jobs/${jobId}/errors?page=${this.jobErrorsPage}&limit=20`
);
const newErrors = response.errors || [];
this.jobErrors = [...this.jobErrors, ...newErrors];
adminImportsLog.debug('Loaded more job errors:', newErrors.length);
} catch (error) {
adminImportsLog.error('Failed to load more job errors:', error);
this.jobErrorsPage--; // Revert page on failure
} finally {
this.loadingErrors = false;
}
},
/**