AI enrichment: show current vs proposed comparison with color coding
Some checks are pending
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Review panel now shows side-by-side comparison for each field: - Red block "Obecne:" shows current value (what will be replaced) - Green block "Propozycja:" shows AI suggestion - Badge: NOWE (green) for empty fields, ZMIANA (yellow) for updates - New fields are pre-checked, changes are unchecked (safer default) - Unchanged fields are hidden (no noise) - Backend now returns current_data alongside proposed_data Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
25e34d254c
commit
c2fc5abe6d
@ -1051,6 +1051,20 @@ WAZNE:
|
||||
|
||||
logger.info(f"AI enrichment proposal created for {company.name}. Proposal ID: {proposal_id}. Sources: {sources_used}")
|
||||
|
||||
# Get current AI insights for comparison
|
||||
existing_insights = db.query(CompanyAIInsights).filter_by(company_id=company.id).first()
|
||||
current_data = {}
|
||||
if existing_insights:
|
||||
current_data = {
|
||||
'business_summary': existing_insights.business_summary or '',
|
||||
'services_list': existing_insights.services_list or [],
|
||||
'target_market': existing_insights.target_market or '',
|
||||
'unique_selling_points': existing_insights.unique_selling_points or [],
|
||||
'company_values': existing_insights.company_values or [],
|
||||
'certifications': [c.name for c in (company.certifications or []) if c.is_active] if company.certifications else [],
|
||||
'industry_tags': existing_insights.industry_tags or [],
|
||||
}
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': f'Propozycja wzbogacenia danych dla "{company.name}" została utworzona i oczekuje na akceptację',
|
||||
@ -1061,6 +1075,7 @@ WAZNE:
|
||||
'brave_results_count': len(brave_results['news']) + len(brave_results['web']),
|
||||
'website_content_length': len(website_content),
|
||||
'proposed_data': ai_data,
|
||||
'current_data': current_data,
|
||||
'requires_approval': True
|
||||
})
|
||||
|
||||
|
||||
@ -4734,7 +4734,7 @@ function finishAiEnrichment(success) {
|
||||
}
|
||||
}
|
||||
|
||||
function showProposalApprovalButtons(companyId, proposalId, proposedData) {
|
||||
function showProposalApprovalButtons(companyId, proposalId, proposedData, currentData) {
|
||||
// Update modal title
|
||||
document.getElementById('aiModalTitle').textContent = 'Znalezione informacje — wybierz co dodać';
|
||||
document.getElementById('aiCancelBtn').style.display = 'none';
|
||||
@ -4759,37 +4759,59 @@ function showProposalApprovalButtons(companyId, proposalId, proposedData) {
|
||||
'suggested_category': 'Sugerowana kategoria'
|
||||
};
|
||||
|
||||
// Build review panel
|
||||
// Helper: format value for display
|
||||
function formatVal(val) {
|
||||
if (!val) return '';
|
||||
if (Array.isArray(val)) return val.join(', ');
|
||||
return String(val);
|
||||
}
|
||||
|
||||
// Build review panel with current vs proposed comparison
|
||||
var reviewHtml = '<div style="max-height: 50vh; overflow-y: auto; padding: 0 4px;">';
|
||||
var fieldCount = 0;
|
||||
|
||||
for (var key in fieldLabels) {
|
||||
var val = proposedData[key];
|
||||
if (!val || (Array.isArray(val) && val.length === 0)) continue;
|
||||
var newVal = formatVal(proposedData[key]);
|
||||
if (!newVal.trim()) continue;
|
||||
|
||||
var displayVal = '';
|
||||
if (Array.isArray(val)) {
|
||||
displayVal = val.join(', ');
|
||||
} else if (typeof val === 'string') {
|
||||
displayVal = val;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
var curVal = formatVal(currentData[key]);
|
||||
var isNew = !curVal.trim();
|
||||
var isChanged = curVal.trim() && curVal.trim() !== newVal.trim();
|
||||
var isSame = curVal.trim() === newVal.trim();
|
||||
|
||||
if (isSame) continue; // Skip unchanged fields
|
||||
|
||||
if (!displayVal.trim()) continue;
|
||||
fieldCount++;
|
||||
|
||||
var statusBadge = isNew
|
||||
? '<span style="display:inline-block;padding:1px 6px;background:#dcfce7;color:#166534;border-radius:4px;font-size:11px;font-weight:600;margin-left:6px;">NOWE</span>'
|
||||
: '<span style="display:inline-block;padding:1px 6px;background:#fef3c7;color:#92400e;border-radius:4px;font-size:11px;font-weight:600;margin-left:6px;">ZMIANA</span>';
|
||||
|
||||
var currentHtml = '';
|
||||
if (!isNew && curVal) {
|
||||
currentHtml = '<div style="font-size:12px; color:#991b1b; background:#fef2f2; padding:6px 8px; border-radius:4px; margin-bottom:4px; border-left:3px solid #fca5a5;">' +
|
||||
'<span style="font-weight:600; color:#7f1d1d;">Obecne:</span> ' +
|
||||
curVal.substring(0, 200) + (curVal.length > 200 ? '...' : '') +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
var proposedHtml = '<div style="font-size:13px; color:#166534; background:#f0fdf4; padding:6px 8px; border-radius:4px; border-left:3px solid #86efac;">' +
|
||||
'<span style="font-weight:600; color:#14532d;">Propozycja:</span> ' +
|
||||
newVal.substring(0, 300) + (newVal.length > 300 ? '...' : '') +
|
||||
'</div>';
|
||||
|
||||
reviewHtml += '<label style="display:flex; gap:10px; padding:12px; margin-bottom:8px; background:#f9fafb; border:1px solid #e5e7eb; border-radius:8px; cursor:pointer; align-items:flex-start; line-height:1.5;">' +
|
||||
'<input type="checkbox" checked data-field="' + key + '" style="margin-top:4px; width:18px; height:18px; flex-shrink:0;">' +
|
||||
'<input type="checkbox" ' + (isNew ? 'checked' : '') + ' data-field="' + key + '" style="margin-top:4px; width:18px; height:18px; flex-shrink:0;">' +
|
||||
'<div style="flex:1; min-width:0;">' +
|
||||
'<div style="font-weight:600; font-size:13px; color:#1f2937; margin-bottom:2px;">' + fieldLabels[key] + '</div>' +
|
||||
'<div style="font-size:13px; color:#4b5563; word-break:break-word;">' + displayVal.substring(0, 300) + (displayVal.length > 300 ? '...' : '') + '</div>' +
|
||||
'<div style="font-weight:600; font-size:13px; color:#1f2937; margin-bottom:4px;">' + fieldLabels[key] + statusBadge + '</div>' +
|
||||
currentHtml +
|
||||
proposedHtml +
|
||||
'</div>' +
|
||||
'</label>';
|
||||
}
|
||||
|
||||
if (fieldCount === 0) {
|
||||
reviewHtml += '<p style="text-align:center; color:#64748b; padding:20px;">Nie znaleziono nowych informacji do dodania.</p>';
|
||||
reviewHtml += '<p style="text-align:center; color:#64748b; padding:20px;">Nie znaleziono nowych informacji do dodania. Profil firmy jest aktualny.</p>';
|
||||
}
|
||||
|
||||
reviewHtml += '</div>';
|
||||
@ -4955,9 +4977,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
const insights = data.proposed_data;
|
||||
const proposalId = data.proposal_id;
|
||||
const currentData = data.current_data || {};
|
||||
|
||||
// Show review panel with checkboxes
|
||||
showProposalApprovalButtons(companyId, proposalId, insights);
|
||||
showProposalApprovalButtons(companyId, proposalId, insights, currentData);
|
||||
return;
|
||||
} else {
|
||||
addAiLogEntry('Blad: ' + (data.error || 'Nieznany blad'), 'error');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user