Files
orion/app/modules/prospecting/static/admin/js/scan-jobs.js
Samir Boulahtit 6d6eba75bf
Some checks failed
CI / pytest (push) Failing after 48m31s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / ruff (push) Successful in 11s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 28s
feat(prospecting): add complete prospecting module for lead discovery and scoring
Migrates scanning pipeline from marketing-.lu-domains app into Orion module.
Supports digital (domain scan) and offline (manual capture) lead channels
with enrichment, scoring, campaign management, and interaction tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:59:47 +01:00

88 lines
3.1 KiB
JavaScript

// static/admin/js/scan-jobs.js
const jobsLog = window.LogConfig.createLogger('prospecting-scan-jobs');
function scanJobs() {
return {
...data(),
currentPage: 'scan-jobs',
jobs: [],
loading: true,
error: null,
pagination: { page: 1, per_page: 20, total: 0, pages: 0 },
async init() {
await I18n.loadModule('prospecting');
if (window._scanJobsInit) return;
window._scanJobsInit = true;
if (window.PlatformSettings) {
this.pagination.per_page = await window.PlatformSettings.getRowsPerPage();
}
jobsLog.info('Scan jobs initializing');
await this.loadJobs();
},
async loadJobs() {
this.loading = true;
this.error = null;
try {
const params = new URLSearchParams({
page: this.pagination.page,
per_page: this.pagination.per_page,
});
const response = await apiClient.get('/admin/prospecting/stats/jobs?' + params);
this.jobs = response.items || [];
this.pagination.total = response.total || 0;
this.pagination.pages = response.pages || 0;
} catch (err) {
this.error = err.message;
jobsLog.error('Failed to load jobs', err);
} finally {
this.loading = false;
}
},
async startBatchJob(jobType) {
try {
await apiClient.post('/admin/prospecting/enrichment/' + jobType.replace('_', '-') + '/batch');
Utils.showToast(jobType.replace(/_/g, ' ') + ' batch started', 'success');
setTimeout(() => this.loadJobs(), 2000);
} catch (err) {
Utils.showToast('Failed: ' + err.message, 'error');
}
},
goToPage(page) {
this.pagination.page = page;
this.loadJobs();
},
jobStatusClass(status) {
const classes = {
pending: 'text-yellow-700 bg-yellow-100 dark:text-yellow-100 dark:bg-yellow-700',
running: 'text-blue-700 bg-blue-100 dark:text-blue-100 dark:bg-blue-700',
completed: 'text-green-700 bg-green-100 dark:text-green-100 dark:bg-green-700',
failed: 'text-red-700 bg-red-100 dark:text-red-100 dark:bg-red-700',
cancelled: 'text-gray-700 bg-gray-100 dark:text-gray-100 dark:bg-gray-700',
};
return classes[status] || classes.pending;
},
formatDuration(job) {
if (!job.started_at) return '—';
const start = new Date(job.started_at);
const end = job.completed_at ? new Date(job.completed_at) : new Date();
const seconds = Math.round((end - start) / 1000);
if (seconds < 60) return seconds + 's';
const mins = Math.floor(seconds / 60);
const secs = seconds % 60;
return mins + 'm ' + secs + 's';
},
};
}